Linux——进程(fork与vfork)

1.基本了解:
一个进程,包括代码、数据和分配给进程的资源。fork 函数会新生成一个进程,调用 fork 函数的进程为父进程,新生成的进程为子进程。在父进程中返回子进程的 pid,在子进程中返回 0,失败返回-1。

为什么两个进程的fpid不同呢?

这与fork函数的特性有关。fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
    1)在父进程中,fork返回新创建子进程的进程ID;
    2)在子进程中,fork返回0;
    3)如果出现错误,fork返回一个负值;
 

一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。

2.fork函数的了解:

#include <sys/types.h>
#include <unistd.h>

pid_t  fork(void);

函数返回类型 pid_t 实质是 int 类型,Linux 内核 2.4.0 版本的定义是:

typedef  int  _kenrnel_pid_t;

typedef  _kenrnel_pid_t  pid_t;

 fork 函数会新生成一个进程,调用 fork 函数的进程为父进程,新生成的进程为子进程。
在父进程中返回子进程的 pid,在子进程中返回 0,失败返回-1(此时才能更好理解他的返回值)。

获取进程pid:getpid()


简单判断父子进程demo

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>


int main()
{
	pid_t pid_F;
	pid_t pid_fork;

	pid_F = getpid();
	printf("pid_F=%d\n",pid_F);

	pid_fork = fork();

	if(pid_fork > 0){
	
		printf("This is father\n");
		printf("father pid = %d\n",getpid());
	}else if(pid_fork == 0){
		printf("\n\nThis is child\n");
		printf("child pid = %d\n",getpid());
	}

	return 0;
}

还有一个类似的vfork函数

原型:

#include <sys/types.h>
#include <unistd.h>

pid_t vfork(void);

fork和vfork的区别:

1)fork(): 父子进程的执行次序不确定。

vfork():保证子进程先运行,在它调用 exec(进程替换) 或 exit(退出进程)之后父进程才可能被调度运行。

2)fork(): 子进程拷贝父进程的地址空间,子进程是父进程的一个复制品。

vfork():子进程共享父进程的地址空间(准确来说,在调用 exec(进程替换) 或 exit(退出进程) 之前与父进程数据是共享的

简单的验证demo:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
	pid_t pid;
	int mark = 0;	
	pid = vfork();

	while(1){
	if(pid > 0){
		printf("This is father PID:%d\n",getpid());
		printf("mark:%d\n",mark);
		sleep(2);
		
	}else if(pid == 0){
		printf("This is child PID:%d\n",getpid());
		mark++;
		printf("mark:%d\n",mark);
		sleep(2);
		if(mark > 2){
			printf("child exit!!!\n");
			exit(-1);
		}
	}
	}


	return 0;
}

进程退出:

1.Main函数调用return
在main函数中执行return可以终止进程,并将控制权交给调用函数。一般原则程序执行正常退出return 0,而执行函数出错退出return -1。

2.进程调用exit——标准C库
exit()是一个标准C库函数,执行exit()会进行一些清理工作,最后调用_exit()函数。
函数原型:
void exit(int status);

3.进程调用_exit()或者_Exit(),属于系统调用
_Exit()和_exit()等价,都属于系统调用,使用_exit()会清除其使用的内存空间,并销毁其在内核中的数据结构,关闭进程的所有文件描述符,并结束进程、将控制权交给操作系统。
函数原型:
void _exit(int status);
调用函数需要传入status状态标志,0表示正常结束、若为其它值则表示程序执行过程中检测到有错误发生。
 

父进程等待子进程退出参考下面文章:

(46条消息) 父进程等待子进程退出_杨映春的博客-CSDN博客_父进程不等待子进程结束

什么是孤儿进程? 什么是僵尸进程?
1、孤儿进程
父进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”,此时子进程就叫做孤儿进程。
Linux避免系统存在过多孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程。
Pid==1,init进程(初始化进程)

2、僵尸进程
僵尸进程是当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。(也就是子进程的退出状态不被收集)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值