wait()与waitpid()
当一个进程正常或异常退出时,内核就会向其父进程发送SIGCHLD信号。因为子进程退出是一个异步事件,所以这种信号也是内核向父进程发送的一个异步通知。父进程可以选择忽略该信号,或者提供一个该信号发生时即将被执行的函数,父进程可以调用wait()或waitpid()可以用来查看子进程退出的状态。
pid_t wait(int *status); pid_t waitpid(pid_t pid, int *status, int options);
在一个子进程终止前,wait使其调用者阻塞,而waitpid有一选项可使调用者不用阻塞。 waitpid并不等待在其调用的之后的第一个终止进程,他有若干个选项,可以控制他所等待的进程。 如果一个已经终止、但其父进程尚未对其调用wait进行善后处理(获取终止子进程的有关信息如CPU时间片、释放它锁占用的资源如文件描述符等)的进程被称僵死进程(zombie),ps命令将僵死进程的状态打印为Z。如果子进程已经终止,并且是一个僵死进程,则wait立即返回该子进程的状态。所以,我们在编写多进程程序时,最好调用wait()或waitpid()来解决僵尸进程的问题。
此外,如果父进程在子进程退出之前退出了,这时候子进程就变成了孤儿进程。当然每一个进程都应该有一个独一无二的父进程,init进程就是这样的一个“慈父”,Linux内核中所有的子进程在变成孤儿进程之后都会被init进程“领养”,这也意味着孤儿进程的父进程最终会变成init进程。
system()与popen()函数
如果我们在程序中,想执行另外一个Linux命令时,可以调用fork()然后再exec执行相应的命令即可,但这样相对比较麻烦。Linux系统提供了一个system()库函数,该库函数可以快速创建一个进程来执行相应的命令。
int system(const char *command);
譬如我们想执行ping命令,则可以使用下面的程序片段:
system("ping -c 4 -I eth0 4.2.2.2");
如果这里的 eth0、4.2.2.2 等是一个变量参数,我们则可以使用snprintf()格式化生成该命令:
char cmd_buf[256];
int count = 4;
char *interface="eth0";
char *dst_ip = "4.2.2.2";
snprintf(cmd_buf, sizeof(buf