创建进程fork

1. 进程通信:
1.1在用户空间是不能实现进程间通信的,只能通过Linux内核空间,创建对应的对象,实现进程间通信;对象不同,通信方式名字也就不一样。比如内核创建管道对象,对应的就是管道通信。
1.2,子进程会从 fork( )返回值后的下一条逻辑语句开始运行。这样就避免了不断调用
fork( )而产生无限子孙的悖论。
1.3,父子进程是相互平等的:他们的执行次序是随机的,或者说他们是并发运行的,除非使用特殊机制来同步他们,否则你不能判断他们的运行究竟谁先谁后。
1.4,父子进程是相互独立的:由于子进程完整地复制了父进程的内存空间,因此从内存
空间的角度看他们是相互独立、互不影响的。
1.5,fork( )会使得进程本身被复制(想想细胞分裂),因此被创建出来的子进程和父进
程几乎是一模一样的,说“几乎”意味着子进程并不是 100%为一份父进程的复印件,他们
的具体关系如下:
父子进程的以下属性在创建之初完全一样,子进程相当于搞了一份复制品:
A) 实际 UID 和 GID,以及有效 UID 和 GID。
B) 所有环境变量。
C) 进程组 ID 和会话 ID。
D) 当前工作路径。除非用 chdir()加以修改
E) 打开的文件。
F) 信号响应函数。
G) 整个内存空间,包括栈、堆、数据段、代码段、标准 IO 的缓冲区等等。
而以下属性,父子进程是不一样的:
A) 进程号 PID。PID 是身份证号码,哪怕亲如父子,也要区分开。
B) 记录锁。父进程对某文件加了把锁,子进程不会继承这把锁。
C) 挂起的信号。这些信号是所谓的“悬而未决”的信号,等待着进程的响应,子进程
也不会继承这些信号

2. 线程通信:用户空间就可以实现互相通信,比如全局变量。

3. 进程间通信分类:
a. 管道通信:无名管道、有名管道(文件系统中有名);
b. 信号通信:包括信号的发送、接收、处理;
c. IPC通信:共享内存、消息队列、信号灯;
d. socket通信:一个网络中的两个进程间通信,也是进程间通信的一种;

4. 学习进程间通信的思路可以参考文件IO的思想,他们的思想一致,只是函数的实现实现可能不同:
open: 创建、打开进程通信对象;
write: 向通信对象写入内容;
read: 从通信对象中读取内容;
close: 关闭、删除进程通信对象

5. 创建进程fork函数:

/*类型为 pid_t, 本质是一个整形数*/
pid_t fork(void);

6.获取进程ID
6.1 获取当前进程PID函数如下

#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);

6.2 获取当亲进程的父进程ID函数如下:

#include <sys/types.h>
#include <unistd.h>
pid_t getppid(void);

7.进程退出处理机制
在这里插入图片描述
在使用exit()函数时,还可以注册退出处理函数,意思就是退出的时候会先执行“退出处理函数”,然后刷新库缓存,最后退出线程。注册退出处理API:int atexit(void (*function)(void));

8. 创建进程与退出的例子:

#include "unistd.h"
#include "stdio.h"
#include "sys/types.h"
#include "stdlib.h"
#include <wiringPi.h> 

void routine1(void) // 退出处理函数
{
	printf("child exit handler.\n");
}

void routine2(void) // 退出处理函数
{
 printf("parent exit handler.\n");
}

int main()
{
	
	pid_t pid;
	int process = 0;
	pid = fork();
 
	if(pid ==0)//child process code   second
	{
		int i = 0;
		atexit(routine1);// 注册退出处理函数,执行exit()退出前,执行routine2函数
		for(i=0; i<3; i++)
		{
			printf("child process process=%d\n",process);
			//delayMicroseconds(500*1000);  // 微秒级延迟
			delay(1000); //ms
		}
		exit(0);	//0表示正常退出,同时冲洗缓冲区数据,并执行退出处理函数
	}
  
	if(pid >0)//parent process code   first
	{
		int i = 0;
		process = 1;
		atexit(routine2);// 注册退出处理函数,执行exit()退出前,执行routine2函数
		printf("PPID:%d, PID:%d\n", getppid(), getpid() );
		for(i=0; i<3; i++)
		{
			printf("parent process process=%d\n",process);
			//delayMicroseconds(500*1000);  // 微秒级延迟
			delay(1000); //ms
		}
		exit(0);	//0表示正常退出,同时冲洗缓冲区数据,并执行退出处理函数
	}  
}

参考:https://blog.csdn.net/wenwen111111/article/details/54633298

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值