fork、vfork函数

fork、vfork函数


每个进程都有一个非负整数表示的唯一ID。所以进程ID可以用来作为其他标志符的一部分来保证其唯一性。

当进程终止后,其ID可以重用。大多UNIX系统实现延迟算法,使赋予新建进程的ID不同于最近终止进程的ID。

系统中有一些专用进程。如ID 为0的进程通常是调度进程,常常称为__交换进程(swapper)__。交换进程是内核的一部分,它并不执行任何磁盘上的程序,所以也称为系统进程。

ID为1的通常是init进程,在自举过程结束时由内核调用。init进程负责在自举结束后启动一个UNIX系统。init进程不会被终止。它是一个普通用户进程,但是以超级用户权限运行。


下面的这些函数可以返回进程的信息:

    #include <unistd.h>

    pid_t  getpid(void);           //返回调用进程的进程ID

    pid_t  getppid(void);        //返回调用进程的父进程ID

    uid_t  getuid(void);          //返回调用进程的实际用户ID

    uid_t  geteuid(void);       //返回调用进程的有效用户ID

    gid_t  getgid(void);         //返回调用进程的实际组ID

    gid_t  getegid(void);      //返回调用进程的有效组ID


**fork函数**

fork函数可以创建一个子进程

    #include <unistd.h>

    pid_t  fork(void);          

fork函数会返回两次,一次是在子进程中,返回值为0; 另一次在父进程中,返回值为fork创建的子进程ID。如过失败则返回-1

子进程和父进程继续执行fork调用后的指令。子进程是父进程的副本,它们共享程序的正文段。

一般fork后子进程常调用exec函数族中函数。所以很多实现并不完全将父进程的的数据段、栈、堆复制到子进程,而是使用__写时复制(Copy On Write)__技术。这些区域会由父进程和子进程共享,内核将它们改变为只读访问权限。当父子进程中任意一个试图修改这些区域,则内核只为修改区域的内存制作一个副本。


fork调用后父子进程的执行顺序是不固定的。如果要求父子进程相互同步,则要求某种形式的进程间通信。


文件共享:

如果fork之前对父进程进行IO重定向,子进程的IO也同样进行了重定向。父进程的所有打开文件描述符会被负责到子进程中。


父子进程的不同:

1.  fork返回值

2.  进程ID

3.  各自的父进程ID

4.  子进程的tms_utime、tms_stime、tms_cutime和tms_ustime均设置为0.

5.  父进程设置的文件锁不会被子进程继承

6.  子进程的未处理的闹钟(alarm)被清除

7.  子进程的未处理信号集被设为空集


fork失败主要原因有:系统中进程太多、或实际用户ID的进程总数超过系统限制(CHILD_MAX规定了每个实际用户ID在任一时刻可具有的最大进程数)。


fork的用法:

1.  一个父进程希望复制自己,使父子进程同时执行不同代码段。

2.  一个进程要执行一个不同的程序。这种情况下,子进程在fork后立即调用exec。

有的系统实现了将fork之后执行exec的操作组合成了一个,并称为spawn。



vfork函数:

vfork函数与与fork相似,但有两者语义不同。

vfork用于创建一个新进程,而该新进程的目的是exec一个新进程。vfork在子进程中调用exec或exit之前,他在父进程空间中运行,不同与fork的COW。

vfork保证子进程先运行,在它调用exec或exit之后父进程才可能被调度运行。

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#define err_sys(info) \
	({	\
		fprintf(stderr, "%s:%d\n", info, strerror(errno));	\
		exit(EXIT_FAILURE);	\
	})

int main(void)
{
	int		var = 6;
	pid_t	pid;

	printf("before vfork\n");
	if((pid = vfork()) < 0)
		err_sys("vfork error");
	else if(pid == 0)
	{
		var++;			//modify parent's variable
		exit(0);
	}

	printf("var = %d\n", var);		//output var = 7
	exit(0);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值