liunx操作系统——进程的创建

Linux主要提供了fork,vfork,clone三种进程创建方法,在Linux源码中,这三个的执行过程是执行fork(),vfork(),clone()时,同过一个系统调用表映射到sys_fork(),sys_vfork(),sys_clone()
,然后三个函数中去调用do_fork()去做具体的创建进程工作,

获取进程
每个进程都有一个ID,系统调用getpid可以得到进程的ID,而getppid可以得到父进程的ID

下面对函数进行说明


getpid函数


表头文件 #include ——#include
定义函数 gid_getpid(void)
函数说明 getpid()用来执行目前进程的组识别码
返回值 返回组识别码

举例说明

#include
#include
#include

int main()
{
        printf("gid is %d\n",getpid) ;
        return 0;
} 

liunx操作系统——进程的创建_第1张图片
这是在我的虚拟机上运行的,不同的系统值可能不同,以下代码都是在我的系统下运行的

getppid函数

表头文件 #include
定义函数 pid_getppid(void)
函数说明 getppid()是用来取得目前进程的父进程识别码
返回值 父进程的识别码

举例说明

#include
#includde
int main()
{
    printf("parent pid = &d\n",getppid());
    return 0;
}

liunx操作系统——进程的创建_第2张图片
启动进程


fork函数

fork()用来创建子进程

表头文件 #include——#include
定义函数 pid_'fork(void)
函数说明 用来创建新的进程
返回值 在父进程中返回子进程的进程号,在子进程中返回0.错误返回-1

举例说明

#include
#include
#include
#include

int main(void)
{
	pid_t child;

	
	child = fork();

	if(child == -1)
	{
		printf("子进程创建不成功\n");
		exit(1);
	}
	else if(child == 0)
	{
        
		printf("我是子进程\n");
        exit(0);
	}
	return 0;

}

liunx操作系统——进程的创建_第3张图片
父进程和子进程并不是相互独立的,相反他们会共用一些东西,在创建一个进程时,子进程只是完全复制父进程的资源,复制出来的子进程有着自己的结构和ID,但却复制父进程的其他资源,例如父进程打开几个文件,那么子进程也有几个打开的文件,但是子进程的改变不会影响父进程,下面举例说明

#include
#include
#include
#include

int main()
{
	int a = 5;
	int b = 2;
	pid_t pid;
	pid = fork();
	if(pid == 0)
	{
        a = a - 4;
		printf("我是子进程:我的ID是——%d,a——%d,b——%d\n",pid,a,b);
	}
	else if(pid < 0)
	{
		perror("fork\n");
	}
	else
	{
        printf("我是父进程:我的ID是——%d,a——%d,b——%d\n",pid,a,b);
	}
	return 0;
}

liunx操作系统——进程的创建_第4张图片
可见,子进程中将变量a的值改为1,而父进程中则保持不变


启动进程,vfork()函数


vfork()函数用于建立一个新的进程

表头文件 #include
定义函数 pid_t vfork(void)
函数说明 vfork()会产生一个新的子进程,其子进程会复制父进程的数据与堆栈空间,并继承父进程的用户代码,组代码,环境变量,已经打开的文件代码,工作目录和资源限制等等。Linux使用copy-on-write(COW)技术,只有当其中一进程试图修改欲复制的空间时才会做真正的复制动作,由于这些继承信息是复制来的,并非指相同的内存空间,因此子进程对这些变量的修改,父进程并不会同步
返回值 如果vfork()成功则在父进程会返回新建立的子进程代码(PID),而在新建立的子进程中则返回0,如果vfork失败则直接返回-1,失败的原因存在于errno中
错误代码 EAGAIN:内存不足,ENOMEM:内存不足,无法配置核心所需的数据结构空间

实例

#include
#include
#include

int main()
{
	if(vfork() == 0)
	{
		printf("我是子进程\n");
		exit(0);
	}
	else
	{
		printf("我是父进程\n");
	}
	return 0;
}

liunx操作系统——进程的创建_第5张图片
vfork系统调用不同有fork,用vfork创建的子进程与父进程共享地址空间,也就是说子进程完全运行在父进程的地址空间上,如果这时子进程修改了某个变量,这将影响到父进程如果上面fork的例子改成vfork,则a,b的值一样
值得注意的是,用vfork()创建的子进程必须显示调用exit()来结束,否则子进程将不能结束

你可能感兴趣的:(学习)