² 进程的创建
在UNIX中,系统调用fork是创建新进程的方法,原型如下:
#include <unistd.h>
pid_t fork();
调用fork创建的子进程,将共享父进程的代码空间,复制父进程数据空间,此时子进程会获得父进程的所有变量的一份拷贝。
如果fork调用失败,返回-1;如果调用成功,则在父进程中返回子进程的标识号,在子进程中返回0。
实例:
² 新程序的执行
1. exec函数族
v exec函数族用新程序的代码覆盖进程中原来的程序代码,并且使进程使用函数提供的命令行参数和环境变量去执行新的程序。
v 函数族调用成功时,系统把一个新程序的地址空间代替调用进程的地址空间并装入新程序的内容,同事忽略原exec函数的返回,不执行exec函数后的所有语句,系统将从新程序的main函数处开始执行。如果调用失败,返回-1。
2. fork-exec 模型 (子进程和父进程的执行顺序问题?)
3. vfork-exec 模型
v 函数vfork与fork区别:vfork创建的子进程并不复制父进程的数据,在随后的exec调用中系统会复制新程序的数据到内存中‚父进程以vfork方式创建子进程后将被阻塞,直到子进程退出或执行exec调用才继续运行。
4. system 模型
#include<stdlib.h>
Int system(char *string)
函数system阻塞调用它的进程,并执行字符串string中shell命令。
² 进程的休眠
unsigned int sleep(unsigned int seconds);
进程调用函数sleep后休眠seconds秒,直到时间结束或收到不可忽略信号为止。
² 进程的终止
void exit(int status);
参数status的低8位记载了进程的终止状态,进程终止后将这个状态返回给它的父进程
² 进程的同步
pid_t wait(int *status);
pid_t waitpid(pid_t pid,int *status,int options);
v Wait挂起调用它的进程,直到它的任一子进程退出或者收到一个不能忽略的信号为止,如果在父进程执行wait调用前就已经有子进程退出,则立刻返回。函数成功调用后返回结束运行子进程的ID,否则返回-1。
v Waitpid用于多个子进程的操作,如等待特定子进程等。
实例1:
#include <stdio.h>
#include <unistd.h>
int main()
{
pid_t i,j;
int status;
if((i=fork())==0)
{
fprintf(stderr,"child begin.pid=%d\n",getpid());
sleep(40);
fprintf(stderr,"child end.pid=%d\n",getpid());
exit(2);
}
j=wait(&status);
fprintf(stderr,"child pid=%d,exit pid=%d,status=%d",i,j,status);
}
实例2:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
int main()
{
pid_t pid1,pid2,pid3;
int status;
while(1)
{
if((pid1=fork())<0)
exit (1);
else if(pid1==0)
{
sleep(30);
exit(0);
}
if((pid2=fork())<0)
exit (1);
else if(pid2==0)
{
sleep(40);
exit(0);
}
fprintf(stderr,"fork child,pid=[%d][%d]\n",pid1,pid2);
pid3=wait(&status);
kill(pid1,SIGTERM);
kill(pid2,SIGTERM);
fprintf(stderr,"kill child.pid=[%d],exit pid=%d,status=%d\n",pid1,pid2,pid3,status);
pid3=wait(&status);
sleep(1);
}
}