APUE 学习笔记4: Unix Process Control 进程控制

Posted elloop

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了APUE 学习笔记4: Unix Process Control 进程控制相关的知识,希望对你有一定的参考价值。

前言

本文是APUE第四章:文件和目录知识点的总结和代码实践的总结。

关键点

  • fork

  • vfork

  • exit

  • exec系列

  • wait, waitpid, waiid

实践代码

process_controll.cpp

#include "include/inc.h"
#include "include/apue.h"
#include <string>
using std::string;

NS_BEGIN(elloop);


// demonstrate sub-process holds a copy of parent process.
int globalVar = 100;
BEGIN_TEST(ProcessControll, Fork, @@);

string buff("content from buff\\n");

int localV = 1;
ERR_IF(write(STDOUT_FILENO, buff.c_str(), buff.length()) != buff.length(), err_ret, "fail to write buff");

// printf("before fork!");
printf("before fork!\\n");    // \\n will flush stdout.

// fflush(STDOUT_FILENO);       // fflush(FILE*), not fd.
// fflush(stdout);              // flush stdout so the "before fork" won't be copied into sub-process.

pid_t pid(0);
if ((pid = fork()) < 0) 
    err_sys("fail to fork");

else if (pid == 0) 
    // child process.
    ++globalVar;
    ++localV;

else 
    // > 0, parent process.
    sleep(2);


printf("pid: %ld, globalVar: %d, localV: %d\\n", (long)getpid(), globalVar, localV);

END_TEST;


int globalVar2 = 10;
BEGIN_TEST(ProcessControll, Vfork, @@);

int localV = 1;
printf("before vfork!\\n");
pid_t pid(0);
if ((pid = vfork() ) < 0) 
    err_sys("fail to vfork");

else if (pid == 0) 
    // child
    ++globalVar2;
    ++localV;
    _exit(0);
    // exit(0);        // 60338 Segmentation fault: 11


printf("pid: %ld, globalVar2: %d, localV: %d\\n", (long)getpid(), globalVar2, localV);
// pid: 60416, globalVar2: 11, localV: 2

END_TEST;

void printExit(int status) 
    if (WIFEXITED(status)) 
        printf("normal termination, exit status = %d\\n", WEXITSTATUS(status));
    
    else if (WIFSIGNALED(status)) 
        printf("abnormal termination, signal number = %d%s\\n", WTERMSIG(status),
#ifdef WCOREDUMP
                WCOREDUMP(status) ?  " (core file generated)" : "");
#else
                "");
#endif
    
    else if (WIFSTOPPED(status)) 
        printf("child stopped, signal number = %d\\n", WSTOPSIG(status));
    


BEGIN_TEST(ProcessControll, ExitStatus, @@);

pid_t pid;
int st;

pid = fork();
ERR_IF_NEG(pid, err_sys, "fail to fork");
if (pid == 0) 
    exit(7);

ERR_IF(wait(&st) != pid, err_sys, "wait error");
printExit(st);

pid = fork();
ERR_IF_NEG(pid, err_sys, "fail to fork");
if (pid == 0) 
    abort();

ERR_IF(wait(&st) != pid, err_sys, "wait error");
printExit(st);


pid = fork();
ERR_IF_NEG(pid, err_sys, "fail to fork");
if (0 == pid) 
    st /= 0;

ERR_IF(wait(&st) != pid, err_sys, "wait error");
printExit(st);

END_TEST;

BEGIN_TEST(ProcessControll, Waitpid, @@);

pid_t pid;
pid = fork();
ERR_IF_NEG(pid, err_sys, "fail to fork");
if (0 == pid) 
    // first child
    pid = fork();
    ERR_IF_NEG(pid, err_sys, "fail to fork");
    if (pid > 0) 
        exit(0);    // first child terminate.
    

    // second child continuing... will be inherited by init process.
    sleep(2);
    printf("parent pid: %ld\\n", (long)getppid());
    exit(0);


// parent process, wait for the first child.
ERR_IF(waitpid(pid, NULL, 0) != pid, err_sys, "waitpid error");     // NULL means don't care about the termination status of the child process.
exit(0);

END_TEST;


BEGIN_TEST(ProcessControll, RaceCondition, @@);

auto printChar = [](char* str) 
    char*   ptr;
    int     c;
    setbuf(stdout, NULL);
    for (ptr = str; (c = *ptr++) !=0; ) 
        putc(c, stdout);
    
;

pid_t pid;
pid = fork();
ERR_IF_NEG(pid, err_sys, "fail to fork");
if (0 == pid) 
    printChar("print char in child process\\n");

else 
    printChar("print char in parent process\\n");


END_TEST;


RUN_GTEST(ProcessControll, Exec, @@);

pid_t pid;
pid = fork();
ERR_IF_NEG(pid, err_sys, "fail to fork");

const char    *envInit[] = "USER=nonono", "PATH=/tmp", NULL;
if (0 == pid) 
    int ret = execle("/Users/elloop/codes/temp/echoall", "echoall-elloop", "arg1", "arg-2", (char*)0, envInit);
    ERR_IF_NEG(ret, err_sys, "execle error");


ERR_IF_NEG(waitpid(pid, NULL, 0), err_sys, "wait error");

pid = fork();
ERR_IF_NEG(pid, err_sys, "fail to fork");
if (0 == pid) 
    int ret = execlp("echoall", "echoall-arg0", "only 1 arg", (char*)0);
    ERR_IF_NEG(ret, err_sys, "execlp error");


END_TEST;

NS_END(elloop);

错误总结

/*
 * error committed:
 *
 *      1. use int as pid type. 
 *          should be pid_t.
 *
 *      2. use (pid>0) as the fork() and vfork() return value to the child process.
 *          should be (pid == 0) to the child process.
 *
 *      3. use getpid() to get parent pid in Waitpid test case.
 *          should use getppid().
 *
 *      4. RaceCondition test case, don't act as book say. there is no intermixing of output from the two processes.
 *          should be tested in single core cpu machine.
 */

作者水平有限,对相关知识的理解和总结难免有错误,还望给予指正,非常感谢!

在这里也能看到这篇文章:github博客, CSDN博客, 欢迎访问

以上是关于APUE 学习笔记4: Unix Process Control 进程控制的主要内容,如果未能解决你的问题,请参考以下文章

APUE 学习笔记1: Unix文件IO

APUE 学习笔记1: Unix文件IO

APUE 学习笔记2: Unix文件和目录

APUE 学习笔记2: Unix文件和目录

unix环境高级编程学习笔记

unix环境高级编程(第三版)中apue.h文件的配置问题