C++学习记录 - 进程创建

C++学习记录 - 进程创建,第1张

文章目录
  • 1. 创建进程
  • 2. exec函数族
    • 2.1 execlp
    • 2.2 execl
  • 3. 回收子进程
    • 3.1 wait函数
    • 3.2 waitpid函数
  • 4. 进程间通信(IPC)
    • 4.1 管道(PIPE)
    • 4.2 有名管道(FIFO)
    • 4.3 共享映射区(共享内存)
    • 4.4 本地套接字

1. 创建进程

c/c++中,使用fork()函数创建一个进程。

pid_t pid = fork();

子进程自fork()以后开始执行。

fork()函数返回值,为pid_t类型,父子进程依靠pid的不同进行区分。如果fork失败,pid为-1;如果fork成功的话,对于父进程来说,pid是一个正整数,对于子进程来说,pid为0。

子进程创建后,为了节省资源,父子进程之间的共享,遵循读时共享,写时复制的原则。

父子进程共享:1. 文件描述符。 2. mmap建立的映射区。注意,程序中的全局变量什么的,都是独立的,不共享。

fork以后,父进程先执行还是子进程先执行,取决于内核所使用的进程调度算法

2. exec函数族

进程当中去执行另外的程序可以使用exec函数族。

当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行,调用exec并不会创建新的进程,所以调用exec前后该进程的id并未改变。

2.1 execlp 2.2 execl 3. 回收子进程

孤儿进程:父进程比子进程先结束,则该子进程为孤儿进程。此时,子进程的父进程成为init进程,称为init进程领养孤儿进程。但是,实际测试发现,在ubuntu16.04环境下,不是被init进程领养,而是被/sbin/upstart进程领养

僵尸进程:子进程进程终止,父进程尚未回收,子进程残留资源(PCB)存放于内核中,变成僵尸进程。
使用kill命令无法终止僵尸进程,因为kill命令只能用来终止进程,而僵尸进程已经终止了。

3.1 wait函数
#include 
#include 

pid_t waitpid(pid_t pid, int *status, int options);
  • 阻塞等待子进程退出
  • 回收子进程残留资源
  • 获取子进程结束状态(退出原因)

一个wait函数只能回收一个子进程,如果有多少子进程的话,谁先结束,就回收谁。

3.2 waitpid函数
#include 
#include 

pid_t waitpid(pid_t pid, int *status, int options);

功能上包含了wait函数。

4. 进程间通信(IPC)
  • 管道(使用最简单)
  • 信号(开销最小)
  • 共享映射区(也叫共享内存)(无血缘关系)
  • 本地套接字(最稳定)
4.1 管道(PIPE)
  • 管道是一个伪文件,是内核中的一块缓冲区(默认4k,可以通过ulimit -a查看)。

  • 管道一端读,一端写。

  • 管道是半双工通信(单向交替传输)。

  • 管道中的数据,读出了就没了,管道不进行保存,也就是说不能反复读取。

  • 管道只能在有血缘关系的进程间使用。

关键函数是pipe()

#include 

int pipe(int pipefd[2]);

// fd[0] 读端。
// fd[1] 写端。

4.2 有名管道(FIFO) 4.3 共享映射区(共享内存)
#include 

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

有血缘关系的进程间通信,测试代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 


using std::cout;
using std::cin;
using std::endl;

int var = 100;

int main(int argc, char const *argv[])
{   

	
	int *p;
	int len = 4;  // 建立映射区的大小

	
	p = (int *)mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
	
	if(p == MAP_FAILED){  // 注意  不是 p == -1
		cout << "mmap error" << endl;
		return -1;
	}
	
	pid_t pid = fork();
	if(pid == 0){
		*p = 2000;
		var = 1000;
		printf("child,*p = %d, var = %d\n", *p, var);

	}else{
	
		// 父进程
		sleep(1);
		printf("parent,*p = %d, var = %d\n", *p, var);   // 这里的var输出100,因为父子进程间不共享全局变量
		wait(nullptr);
		
		
		int ret = munmap(p, len);
		if(ret == -1){
			cout << "munmap error" << endl;
			return -1;
		}
	
	}
	

	
    return 0;
}
  • MAP_SHARED 共享映射,父子进程共享映射区。
  • MAP_PRIVATE 私有映射,父子进程各自独占映射区。
4.4 本地套接字

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/867259.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-12
下一篇2022-05-12

发表评论

登录后才能评论

评论列表(0条)

    保存