Linux的四大要素:
1. 一段供进程执行的程序,该程序可以被多个进程执行。
2. 独立的内核堆栈。
3. 进程控制快(task_struct:有了这个数据结构,进程才能成为内核调度的一个基本单位接受内核的调度。同时,这个结构还记录着进程所占用的各项资源。
4. 独立的存储空间:即拥有专有的用户空间,除了前面的内核空间还有用户空间。
c语言中派生进程的创建需要include下面的包:
#include <unistd.h>
pid_t fork(void);
该方法返回pid_t。如果返回-1,则创建子进程失败。
使用fork之前的代码都在父进程中执行,而fork之后的代码会在父进程和子进程之间执行。fork调用会执行两次返回(父进程和子进程),当pid的值为0的时候可以判断为子进程。
可以看一个fork的例子:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> int main() { printf("Test\n"); pid_t pid; //定义一个进程ID pid = fork(); //fork.在fork之前是一个进程运行,而fork之后是两个进程在运行了。 if (pid < 0) { printf("fork error!\n"); exit(1); } if (pid == 0) { printf("child process! PID:%d\n", getpid()); //如果pid等于0,子进程,getpid()方法获取当前的进程ID } else { printf("parent process! PID:%d\n", getpid()); //父进程 } return 0; }
pid_t vfork(void)
看一个vfork例子:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> int main() { printf("Test\n"); pid_t pid; //定义一个进程ID pid = vfork(); //vfork 父进程会被挂起,而子进程结束后才会继续执行父进程 if (pid < 0) { printf("fork error!\n"); exit(1); } if (pid == 0) { printf("child process! PID:%d\n", getpid()); //如果pid等于0,子进程,getpid()方法获取当前的进程ID exit(1); //父进程会等待子进程结束,子进程调用exit或者exec函数的时候,父进程的挂起状态会解除 } else { printf("parent process! PID:%d\n", getpid()); //父进程 } return 0; }
Test child process! PID:2636 parent process! PID:2635
#include <sys/types.h> #inculde <sys/wait.h> pid_t wait(int *status);
wait函数调用成功则返回等待状态的进程PID;如果失败,则返回-1
当参数status不为NULL的时候,可以用下面的宏来解析状态:
WIFEXITED(status) 如果子进程正常结束则为非 0 值。
WEXITSTATUS(status) 取得子进程 exit()返回的结束代码,一般会先用 WIFEXITED 来判断是否正常结束才能使用此宏。
WIFSIGNALED(status) 如果子进程是因为信号而结束则此宏值为真
WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般会先用 WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status) 如果子进程处于暂停执行情况则此宏值为真。一般只有使用 WUNTRACED 时才会有此情况。
WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用 WIFSTOPPED 来判断后才使用此宏。
一个例子:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> void check_exit(int status); int main() { printf("Test\n"); pid_t pid; //定义一个进程ID int status; pid = vfork(); //vfork 父进程会被挂起,而子进程结束后才会继续执行父进程 if (pid < 0) { printf("fork error!\n"); exit(1); } if (pid == 0) { printf("child process! PID:%d\n", getpid()); //如果pid等于0,子进程,getpid()方法获取当前的进程ID exit(1); //父进程会等待子进程结束,子进程调用exit或者exec函数的时候,父进程的挂起状态会解除 } else { if (wait(&status) != pid) {//等待操作 printf("wait Error!\n"); exit(0); } printf("parent process! PID:%d\n", getpid()); //父进程 check_exit(status); //检测返回的状态 } return 0; } void check_exit(int status) { if(WIFEXITED(status)) printf("Wait Success eixt\n"); else if(WIFSIGNALED(status)) printf("killed by signal\n"); else if(WIFSTOPPED(status)) printf("stopped by signal\n"); else if(WIFCONTINUED(status)) printf("continued"); }
输出:
Test child process! PID:2705 parent process! PID:2704 Wait Success eixt
#include <sys/types.h> #inculde <sys/wait.h> pid_t waitpid(pid_t pid, int *status, int option);
pid:
pid<-1 等待进程组识别码为 pid 绝对值的任何子进程。
pid=-1 等待任何子进程,相当于 wait()。
pid=0 等待进程组识别码与目前进程相同的任何子进程。
pid>0 等待任何子进程识别码为 pid 的子进程。
status:状态
option:
0 进程挂起,等待其结束
WNOHANG 如果没有任何已经结束的子进程则马上返回, 不予以等待。
WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。
waitpid能指定具体的线程ID,以及可以选择不同的等待方式,所以比wait更加灵活一些
例子:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> void check_exit(int status); int main() { printf("Test\n"); pid_t pid; //定义一个进程ID int status; pid = vfork(); //vfork 父进程会被挂起,而子进程结束后才会继续执行父进程 if (pid < 0) { printf("fork error!\n"); exit(1); } if (pid == 0) { printf("child process! PID:%d\n", getpid()); //如果pid等于0,子进程,getpid()方法获取当前的进程ID exit(1); //父进程会等待子进程结束,子进程调用exit或者exec函数的时候,父进程的挂起状态会解除 } else { if (waitpid(-1, &status, 0) != pid) {//等待所有子进程,然后主进程挂起状态等待返回 printf("wait Error!\n"); exit(0); } printf("parent process! PID:%d\n", getpid()); //父进程 check_exit(status); //检测返回的状态 } return 0; } void check_exit(int status) { if(WIFEXITED(status)) printf("Wait Success eixt\n"); else if(WIFSIGNALED(status)) printf("killed by signal\n"); else if(WIFSTOPPED(status)) printf("stopped by signal\n"); else if(WIFCONTINUED(status)) printf("continued"); }
输出:
Test child process! PID:2705 parent process! PID:2704 Wait Success eixt
1. 常用的c标准进程终止函数
void exit(int status);
void abort(void)
int atexit(void (* function)(void))
int on_exit(void (* function)(int, void*), void *arg)