1.waitpid 函数

函数原型:pid_t wait_pid(pid_t pid, int *status, int options);
其中

  1. pid1.2 用的比较多
1.pid > 0 : 某个子进程的pid
2.pid == -1:回收所有子进程
回收的时候循环回收
while( (wpid = waitpid(-1,&status,xx)) != -1 )
3.pid == 0 :回收当前进程组所有子进程
4.pid < 0 : 子进程的pid取反(相当于加“-“”)
  1. options
    0 : waitpid 阻塞
    WNOHANG : 非阻塞
  2. 返回值
    -1 : 回收失败,没有子进程
    大于0 : 被回收子进程的pid
    如果为非阻塞 0 : 子进程处于运行状态
  3. 参数 : status
    判断子进程是如何死的:
    a. 正常退出
    b. 被某个信号杀死
    c. 如果不关心怎么死的 就写成 NULL
  4. 调用一次只能回收一个子进程

2. 进程间通信相关概念

一. 神马是进程间通信(IPC):InterProcess communication
二.进程间通信常用的4种方式

  1. 管道:简单
  2. 信号:系统开销小
  3. 共享映射区:有无血缘关系的都可以
  4. 本地套接字:稳定

3. 管道(匿名):

一.管道的概念

  1. 本质:
    a.内核缓冲区
    b.伪文件 - 不占用磁盘空间
  2. 特点:
    a.读端,写端对应两个文件描述符
    数据写端流入,读端流出
    b.操作管道的进程被销毁之后,管道自动被释放
    c.管道默认是阻塞的。读写。

二.管道的原理

  1. 内部实现方式是队列:环形队列,先进先出
  2. 缓冲区的大小:默认4K,会根据实际情况做适当调整

三.管道的局限性

  1. 队列:内部只能读取一次,不能重复读取
  2. 半双工
    a.单工:遥控器
    b.半双工:对讲机(数据传输方向是单向的)
    c.双工:电话
  3. 匿名管道:适用于有血缘关系的进程

四. 创建匿名管道
Int pipe(int fd[2]);
fd-传出参数 fd[0]-读端 fd[1]-写端

4. 父子进程使用管道通信

  1. 单个进程能否使用管道完成读写操作? 可以的。
  2. 注意事项
    进程-----需要关闭写端
    进程-----需要关闭读端
    Linux系统编程day2知识点总结回顾1

5. 强化练习

a. 父子进程间通信,实现ps aux | grep bash
b. 兄弟进程间通信,实现ps aux | grep bash
a.父子间进程通信的实现思路
Linux系统编程day2知识点总结回顾1
练习a 代码:

// An highlighted block
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<string.h>
#include<fcntl.h>

int main(int argc, const char *argv[])
{
	int fd[2];
	int ret = pipe(fd);
	if(ret == -1)
	{
		perror("pipe error");
		exit(1);
	}

	pid_t pid = fork();
	if(pid == -1)
	{
		perror("fork error");
		exit(0);
	}

	//parent ps aux
	if(pid > 0)
	{
		close(fd[0]);
		dup2(fd[1],STDOUT_FILENO);
		execlp("ps", "ps", "aux", NULL );
		perror("execlp");
		exit(1);
	}
	//child grep "bash"
	else if(pid == 0)
	{
		close(fd[1]);
		dup2(fd[0], STDIN_FILENO);
		execlp("grep", "grep", "bash", NULL);
		perror("execlp");
	}
	printf("pipe[0] = %d\n", fd[0]);
	printf("pipe[1] = %d\n", fd[1]);

	close(fd[0]);
	close(fd[1]);
	return 0;
}

a.兄弟间进程通信的实现思路
Linux系统编程day2知识点总结回顾1

练习a 代码:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<string.h>
#include<sys/wait.h>

int main(int argc, const char *argv[])
{
	int i = 0; //通过循环因子判断 兄弟进程和 父进程
	int num = 2; //fork 两个 兄弟进程
	int fd[2];
	int ret = pipe(fd);
	if(ret == -1)
	{
		perror("pipe error");
		exit(1);
	}
	for(i = 0; i < num; i++)
	{
		pid_t pid = fork();
		if(pid == -1)
		{
			perror("fork error");
			exit(1);
		}
		if(pid == 0)    //只创建兄弟进程
		{
			break;
		}
	}

	//子进程1 ps aux
	if(i == 0)
	{
		close(fd[0]);
		dup2(fd[1],STDOUT_FILENO);
		execlp("ps", "ps", "aux", NULL );
		perror("execlp");
		exit(1);
	}
	//子进程2 grep "bash"
	if(i == 1)
	{
		close(fd[1]);
		dup2(fd[0], STDIN_FILENO);
		execlp("grep", "grep", "bash", NULL);
		perror("execlp");
	}
	//父进程
	if(i == num)
	{
		close(fd[0]);
		close(fd[2]);
		//回收子进程
		pid_t wpid;
		while( (wpid = waitpid(-1, NULL, WNOHANG) != -1))
		{
			if(wpid == 0)  //子进程 正在运行
			{
				continue;
			}
			printf("child died pid = %d\n", wpid);
		}
	}
	printf("pipe[0] = %d\n", fd[0]);
	printf("pipe[1] = %d\n", fd[1]);

	return 0;
}

2019/2/25 胡云层 于南京

相关文章: