(三)进程常用方法:
可通过fork()创建进程,fork()函数格式为:
#include <unistd.h>
pid_t fork(void);
fork()函数无参数,直接创建一个新进程,新进程为调用fork()的进程的子进程,返回一个进程标识ID(用于区分父进程与子进程,父进程中返回的标识ID是新创建的子进程ID,而子进程中返回的ID为0)
可通过exit()结束进程,exit()函数格式为:
#include <stdlib.h>
void exit(int status);
参数status为进程结束时的状态,当调用该函数结束子进程时,status会作为父进程中wait()函数的第一个参
wait()函数格式为:
#include <sys/wait.h>
pid_t wait(int* stat_loc);
stat_loc为等待的子进程结束状态值的指针(由子进程exit(int status)中的参数status提供,成功为0否则对应错误数字) ,当然,我们设为NULL
,函数仍可正常运行。
wait()
返回值是返回结束的子进程标识 ID;
wait()
使父进程的状态变为等待态,直到父进程中任意一个子进程成功退出并返回结束状态值,父进程才可进入就绪态;
如果在wait()
被调用时已经有可用的结束状态值,那么wait()
会立即返回
注意!!
(1)如果在等待过程中出现错误(如已经没有可等待的子进程),wait()
将返回-1
(2)父进程不能直接等待子进程的子进程
wait函数作用:
1使子进程某些指令在执行父进程前完成
2 使用wait()让父进程等待所有子进程结束后结束,避免僵尸进程的出现
举个栗子:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main() {
int pid = fork();
if (pid != 0) {
int status;
int result = wait (&status);
if (result == -1 || status != 0) {
printf("%s\n", "额,没收到儿子的回信");
return -1;
} else {
printf("%s\n", "我是父亲");
}
} else {
int second_pid = fork();
if (second_pid != 0) {
int new_status;
int new_result = wait (&new_status);
if (new_result == -1 || new_status != 0) {
printf("%s\n", "额,没收到孙子的回信");
exit (-1);
} else {
printf("%s\n", "我是儿子");
exit(0);
}
} else {
printf("%s\n", "我是孙子");
exit(0);
}
}
return 0;
}
waitpid()函数格式:
#include <sys/wait.h>
pid_t waitpid (pid_t pid, int* stat_loc, int options);
waitpid()可指定一个标识ID来等待指定进程(当pid > 0时等待标识ID为pid的子进程,当pid == -1时等待任意子进程,当pid == 0时等待进程组标识ID与父进程相同的子进程,当pid < -1时,等待任意进程组标识ID为pid绝对值的进程)
options代表特殊选项(目前Linux只支持WNOHANG和WUNTRACED两个选项,这是两个常数,可用"|"运算符连接使用,当options为0时代表没有特殊选项)
关于特殊选项:
——WNOHANG :若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待,若结束,则返回该子进程的ID
——WUNTRACED 若子进程进入暂停状态则马上返回,此时子进程的结束状态不予理会
所以,当pid = -1,options = 0时,waitpid()等价于wait()
说了以上四个有关进程的函数,它可以用在哪呢?
多进程的应用有很多,比如在网络编程中,每当服务器接收到一个请求,主进程就会用fork()产生一个新进程去处理那个请求,而父进程继续等待其它请求。大家可以自己去探索发现~
如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢