Linux进程管理(一)
????父进程查询子进程的退出状态可以用wait/waitpid函数。?如何避免僵尸进程????当一个子进程结束运行时,它与其父进程之间的关联还会保持到父进程也正常地结束运行或者父进程调用了wait/waitpid才告终止。????进程表中代表子进程的数据项是不会立刻释放的,虽然不再活跃了,可子进程还停留在系统里,因为它的退出码还需要保存起来以备父进程中后续的wait/waitpid调用使用。它将称为一个“僵尸进程”。????调用wait或者waitpid函数查询子进程退出状态,此方法父进程会被挂起(waitpid可以设置不挂起)。如果不想让父进程挂起,可以在父进程中加入一条语句:signal(SIGCHLD,SIG_IGN);表示父进程忽略SIGCHLD信号,该信号是子进程退出的时候向父进程发送的。也可以不忽略SIGCHLD信号,而接收在信号处理函数中调用wait/waitpid。????而在运维中常用的手段是杀死父进程,这样子进程会由init进程接管,由它来清理子进程的状态——init周期性的调用wait来回收僵尸。?wait是waitpid的特例????当一个进程终止之后,内核向父进程发送一个SIGCHLD。默认这个信号被忽略,进程可以通过singnal()或者sigaction()系统调用来处理这个信号。父进程希望得到子进程终止的更多信息,比如返回值,甚至显式地等待这个事件的到来,这就是wait或者waitpid,它们可以做:????1)阻塞,如果子进程仍然在执行。????2)立即返回,包含子进程的终止状态,如果一个子进程终止,等待它的终止状态被获取。????3)返回错误,如果它没有子进程。?1. wait & waitpid的区别:????1)wait会阻塞调用者,直到一个子进程终止,而waitpid有一个设置不阻塞的选项。????2)waitpid不一定是等待第一个终止的子进程,他有一些选项来控制进程的等待。?2. wait & waitpid的相同点:? ? The wait() system call suspends execution of the calling process ?until one ?of ?its children terminates.?? ? The call?wait(&status);?is equivalent to?waitpid(-1, &status, 0);?3.八、exec函数当进程调用exec时,当前进程的镜像被由path标定的程序加载到内存中代替。下面是exec一族函数:?? ? #include <unistd.h> ?? ? ??? ? int execl(const char *path,const char *arg,...); ?? ? int execv(const char *path,char * const argv[]); ?? ? int execle(const char *path,const char *arg,...); ?? ? int execve(const char *path,char *const argv[], char * const envp[]); ?? ? int execlp(const char *path,const char *arg,...); ?? ? int execvp(const char *path, char *const argv); ???区别:1)前四个参数path代表路径名,后两个代表文件名(不包含路径信息)。如果文件名中包含反斜线,作为一个路径名如果否则从PATH环境变量中找可执行的文件。如果execlp或者execvp找到了可以执行的文件,但是不是机器可执行的,那么就假设这是一个shell脚本,调用/bin/sh执行该shell脚本。2)execl、execle、execlp使用的是参数列表,需要以NULL终止,而其他的几个带v的是一个数组参数,参数数组也要以NULL终止。3)execle、execve传递环境列表到新的程序中。这里面只有execve是系统调用,其他都是函数。例子:?? ? int ret?= execl("/bin/vi","vi",NULL); ?? ? if(ret == -1) ?? ? ? ? perror("execl"); ???下面一个例子,要使用vi打开以及文件编辑:?? ? int ret?= execl("/bin/vi","vi","/home/fuliang/books.txt",NULL); ?? ? if(ret == -1) ?? ? ? ? perror("execl"); ???成功调用execl之后,改变的不仅是地址空间和进程映像,而且还改变进程一下属性:1)任何pending signals都被丢弃。2)任何要捕获的信号都置成默认的行为。因为信号处理函数不在该进程的地址空间了。3)任何的内存锁都被释放。4)很多线程属性被设置为默认值。5)任何和进程内存相关,包括内存映射文件,都被丢弃。6)任何在用户空间存在的包括C语言库,比如atexit的行为被丢弃。没有改变的进程属性:进程pid,父进程id,优先级,进程所属的用户和组。?execvp例子:?? ? const char *args[] = {"vi","/home/fuliang/books.txt",NULL}; ?? ? int ret?= execvp("vi",args); ?? ? if( ret == -1 ) ?? ? ? ? perror("execvp"); ??失败返回-1,并设置errno:1)E2BIG:参数列表或者环境变量envp太长。2)EACCESS:进程没有搜索path的权限,path不是一个普通文件,目标文件不可执行,文件系统被mounted为不可读。3)EFAULT:所给的指针不合法。4)EIO:底层的I/O发生错误。5)EISDIR:path或者解释器是一个目录。6)ELOOP:解析path的时候遇到太多的软链。7)EMFILE:调用进程超过了打开文件的限制。8)ENFILE:系统打开文件数目超过限制。9)ENOENT:path不存在,或者以来的共享库不存在。10)ENOEXEC:目标path是一个不合法的二进制文件或者是不同的机器架构。11)ENOMEM:没有足够的内核内存来执行新的程序12)ENOTDIR:path不是一个目录.13)ETXTBSY:目标文件正被其他的进程写?九、Launching and Waiting for a New ProcessANSI C和POSIX都定义了一个接口,他结合了创建一个进程并且等待它的结束:?? ? #include <stdlib.h> ?? ? ??? ? int system(const char *command); ??system一般用于执行一个简单的工具或者shell脚本。成功返回命令的执行状态,如果command是NULL,则返回非0整数。在执行command命令式,SIGCHILD被阻塞,SIGINT和SIGQUIT被忽略。忽略SIGINT和SIGQUIT有几个含义,尤其system在一个循环里被执行,这时你需要保证程序检查子进程的状态。?? ? do{ ?? ? ? ? int ret?= system("ls -l"); ?? ? ? ? if(WIFSIGNALED(ret) && WTFERMSIG(ret) == SIGINT || WTERMSIG(ret) == SIGQUIT)) ?? ? ? ? ? ? break; ?? ? }while(1); ???使用fork、waitpid简单实现system:?? ? int my_system(const char *cmd){ ?? ? ? ? int status; ?? ? ? ? pid_pid; ?? ? ??? ? ? ? pid = fork(); ?? ? ? ? if(pid == -1); ?? ? ? ? ? ? return -1; ?? ? ? ? else if(pid == 0){ ?? ? ? ? ? ? const char *argv[4]; ?? ? ? ? ? ? argv[0] = "sh"; ?? ? ? ? ? ? argv[1] = "-c"; ?? ? ? ? ? ? argv[2] = cmd; ?? ? ? ? ? ? argv[3] = NULL; ?? ? ? ? ? ? execv("/bin/sh",argv); ?? ? ? ? ? ? exit(-1); ?? ? ? ? }? ? ??? ? ? ? if( waitpid(pid, &status,0) == -1) ?? ? ? ? ? ? return -1; ?? ? ? ? else if(WIFEXITED(status)) ?? ? ? ? ? ? return WEXITSTATUS(status); ?? ? ??? ? ??? ? ? ? return -1; ?? ? } ???参考:1、 Linux进程管理 ?http://blog.csdn.net/flyqwang/article/details/60399372、《Linux system programming》3、《Unix system programming》4、《Advanced Programming in the Unix Environment》?5、 僵尸进程、wait、waitpid ? ?http://blog.csdn.net/jnu_simba/article/details/8931908