pid_t fork( void);
功能:创建一个新进程
返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1
注:
- fork之后是父进程还是子进程先执行是不确定的,取决于内核的调度算法。
- 父子进程共享代码段,至于数据段、栈段、堆并不对父进程完全复制,作为替代,使用写时复制技术。这些区域由父子进程共享,内核将他们的访问权限变为只读。如果父子进程中的任何一个试图修改这些区域。则内核只为修改区域的那块内存制作一个副本。通常是虚拟存储系统中的一页。
- 父进程中所有打开文件描述符都被复制到子进程中。父子进程每个相同的文件描述符共享一个文件表项。
pid_t vfork( void);
功能:创建一个新进程
返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1
注:
- vfork并不将父进程的地址空间完全复制到子进程中,在调用exec或exit之前它在父进程空间中运行。与父进程共享代码段,数据段,堆栈等。
- vfork保证子进程先运行,在它调用exec或exit之后父进程才可能被调度运行。
- 它产生的子进程刚开始暂时与父进程共享地址空间(其实就是线程的概念了),因为这时候子进程在父进程的地址空间中运行,所以子进程不能进行写操作,并且在儿子“霸占”着老子的房子时候,要委屈老子一下了,让他在外面歇着(阻塞),一旦儿子执行了exec或者exit后,相当于儿子买了自己的房子了,这时候就相当于分家了。
- vfork和fork之间的另一个区别是: vfork保证子进程先运行,在她调用exec或exit之后父进程才可能被调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。由此可见,这个系统调用是用来启动一个新的应用程序。其次,子进程在vfork()返回后直接运行在父进程的栈空间,并使用父进程的内存和数据。这意味着子进程可能破坏父进程的数据结构或栈,造成失败。
pid_t wait (int * status);
功能:使父进程阻塞,等待任一子进程结束。一旦任何一个子进程终止,则取得盖子进程的终止状态并立即返回;参数:status 保存子进程的终止状态返回值:如果它没有任何子进程,则立即出错返回-1.成功返回已终止的子进程PID;
注:
- 进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
- status是由实现定义的,其中某些位表示退出状态(正常返回),其他位表示信号编号(异常返回)。有一位指示是否产生了core文件。
pid_t waitpid(pid_t pid,int * status,int options);
pid:功能:使父进程阻塞,等待特定子进程结束。参数:
status:保存子进程的终止状态pid==-1 等待任一子进程结束,就这一方面,waitpid和wait等效pid<-1 等待其组ID为pid绝对值的任一子进程。主要是父子进程不在同一组进程中。pid==0 等待其组ID等于调用进程组ID的任一子进程,主要是父进程与子进程在同一组进程中。pid>0 等待其进程ID与pid相等的子进程
options:
WNOHANG 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若结束,则返回该子进程的ID。WUNTRACED 若由pid指定的子进程进入暂停状态,并且其状态自暂停以来还未报告过,则马上返回其状态。
WCONTINUED 若由pid指定的子进程在暂停后已经继续,但其状态尚未报告,则返回其状态。
返回值:
出错返回-1.成功返回已终止的子进程PID;
注:
- 子进程正常结束,exit或_exit或Exit返回其退出状态。异常终止,内核产生一个终止状态
- 子进程的结束状态返回后存于 status,底下有几个宏可判别结束情况:
WIFEXITED(status)如果若为正常结束子进程返回的状态,则为真;对于这种情况可执行WEXITSTATUS(status),取子进程传给exit或_eixt的低8位。WEXITSTATUS(status)取得子进程 exit()返回的结束代码,一般会先用 WIFEXITED 来判断是否正常结束才能使用此宏。WIFSIGNALED(status)若为异常结束子进程返回的状态,则为真;对于这种情况可执行WTERMSIG(status),取使子进程结束的信号编号。WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般会先用 WIFSIGNALED 来判断后才使用此宏。WIFSTOPPED(status) 若为当前暂停子进程返回的状态,则为真;对于这种情况可执行WSTOPSIG(status),取使子进程暂停的信号编号。WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用 WIFSTOPPED 来判断后才使用此宏。
pid_t getpid(void);
功能:获得当前进程ID返回值:当前进程ID,此函数总是成功
pid_t getppid(void);
功能:获得父进程ID返回值:父进程ID,此函数总是成功
char *getenv(const char *name)
功能:获得环境变量参数:name:想要获得的环境变量的名字返回值:返回指向环境变量的指针,没有匹配的环境变量时返回NULL例:getenv("PATH");
int
getdtablesize(void);
功能:
返回当前进程能够打开的最大文件描述符个数。
pid_t g
etpgrp(void);
功能:返回调用进程的组ID
pid_t getpgid(pid_t pid)
功能:返回进程ID为pid的组ID,若pid=0.则返回调用进程组ID
返回值:出错返回-1
int setpgid(pid_t pid,pid_t pgid)
功能:将pid进程的进程组ID设置为pgid,如果这两个参数相等,则由pid指定的进程变成进程组组长。如果pid是0,则使用调用进程的进程ID。另外,如果pgid是0,则由pid指定的进程ID用作进程组ID。
一个进程只能为它自己和子进程设置组ID。
返回值:成功返回0,错误返回-1.
例程:
int main()
{
pid_t pid;
int status;
int pids[3];
int i = 0;
for(i = 0; i < 3; i ++)
{
pid = fork();
if (pid > 0)
//father process
{
pids[i] = pid;
printf("new child [%d]\n", pid);
}
else if (pid == 0)
//child process
{
puts("I`m child, I`m going to die");
if(i == 1)
sleep(3);
sleep(1);
exit(20);
}
else
error(EXIT_FAILURE, errno, "fail to fork --->%s:%s:%d\n",
__FILE__, __func__, __LINE__);
}
for(i = 0; i < 3; i ++)
printf("%d\n", pids[i]);
puts("I`m father, waiting for child died ... ...");
waitpid(pids[1], &status, 0);
printf("child %d is dead with [%d]\n", pids[1], WEXITSTATUS(status));
exit(EXIT_SUCCESS);
}