进程的创建
Linux下c语言进程编程有两种方式。
一种是fork();
另一种是vfork();
二者的区别在于
一、fork()创建进程后会拷贝父空间,就是fork()函数之上的代码,的变量,自己独占一份,和父空间原有的变量互不影响;
且fork()的子进程和父进程是同步运行的,可能会出现子进程没结束,父进程就结束了的情况,导致子进程退出状态不被收集,使得子进程成为孤儿进程,虽然linux有一套机制会将这些进程收留pid号为1的init进程上,但是最好还是不要出现这种不收集子进程退出状态的变成
二、vfork()则是不拷贝,直接使用的父空间的变量。与线程有点相似
且vfork()会保证子进程先使用exit退出后才执行父进程
下面是关于进程的创建的简单代码,将fork换成vfork就是vfork()的使用方法了
#include<unistd.h>
#include<stdio.h>
int main(){
pid_t pid;
pid = fork(); //fork的返回值,对于子进程则返回0,对于父进程则返回子进程的pid。
if(pid > 0){ //父进程经过if判断只会走这里
printf("this is father pid :%d\n",getpid()); //getpid函数返回的是当前进程的pid号
}
else if(pid ==0){ //子进程经过if判断只会走这里
printf("this is son pid :%d\n",getpid());
}
else{
printf("create pid fail!!!\n");
}
return 0;
}
为了防止前面提到的父进程先于子进程退出,导致子进程变成孤儿进程,所以需要使用exit()和wait()函数
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *wstatus);
pid_t waitpid(pid_t pid, int *wstatus, int options);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
具体编程思路在这里
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
pid_t pid;
pid = fork();
int statu = 12;
if(pid > 0){
wait(&statu);
printf("exit statu is: %d\n",WEXITSTATUS(statu));//调用了linux中的宏用于解析wait传输到statu地址上的数据为真正放在exit()里面的数据,具体用什么宏看下面的图
printf("this is father pid :%d\n",getpid());
}
else if(pid ==0){
int i = 4;
while(i--){
printf("this is son pid :%d\n",getpid());
}
exit(3);
}
else{
printf("create pid fail!!!\n");
}
return 0;
}
运行的结果在这里
至于剩下的waitpid使用方法如下
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);
//pid:
pid == -1 等待任一子进程。于是在这一功能方面waitpid与wait等效。
pid > 0 等待其进程ID与pid相等的子进程。
pid == 0 等待其组ID等于调用进程的组I D的任一子进程。换句话说是与调用者进程同在一个组的进程。
pid < -1 等待其组ID等于pid的绝对值的任一子进程
//status:
如果不是空,会把状态信息写到它指向的位置,与wait一样
//options:
WNOHANG:非阻塞,就是跟没有一样,一般不用
WUNTRACED:用于追踪那些已经停止了的子进程的退出状态,当然也可以用于还没停止的
WCONTINUED:用于追踪那些停止了之后又被SIGCONT启动的子进程的退出状态