Linux系统编程day2知识点总结回顾1
1.waitpid 函数
函数原型:pid_t wait_pid(pid_t pid, int *status, int options);
其中:
- pid(1.2 用的比较多)
1.pid > 0 : 某个子进程的pid
2.pid == -1:回收所有子进程
回收的时候循环回收
while( (wpid = waitpid(-1,&status,xx)) != -1 )
3.pid == 0 :回收当前进程组所有子进程
4.pid < 0 : 子进程的pid取反(相当于加“-“”)
-
options
0 : waitpid 阻塞
WNOHANG : 非阻塞 -
返回值
-1 : 回收失败,没有子进程
大于0 : 被回收子进程的pid
如果为非阻塞 0 : 子进程处于运行状态 - 参数 : status
判断子进程是如何死的:
a. 正常退出
b. 被某个信号杀死
c. 如果不关心怎么死的 就写成 NULL - 调用一次只能回收一个子进程
2. 进程间通信相关概念
一. 神马是进程间通信(IPC):InterProcess communication
二.进程间通信常用的4种方式
- 管道:简单
- 信号:系统开销小
- 共享映射区:有无血缘关系的都可以
- 本地套接字:稳定
3. 管道(匿名):
一.管道的概念
- 本质:
a.内核缓冲区
b.伪文件 - 不占用磁盘空间 - 特点:
a.读端,写端对应两个文件描述符
数据写端流入,读端流出
b.操作管道的进程被销毁之后,管道自动被释放了
c.管道默认是阻塞的。读写。
二.管道的原理
- 内部实现方式是队列:环形队列,先进先出
- 缓冲区的大小:默认4K,会根据实际情况做适当调整
三.管道的局限性
- 队列:内部只能读取一次,不能重复读取
-
半双工:
a.单工:遥控器
b.半双工:对讲机(数据传输方向是单向的)
c.双工:电话 - 匿名管道:适用于有血缘关系的进程
四. 创建匿名管道
Int pipe(int fd[2]);
fd-传出参数 fd[0]-读端 fd[1]-写端
4. 父子进程使用管道通信
- 单个进程能否使用管道完成读写操作? 可以的。
-
注意事项:
父进程读-----需要关闭写端
子进程写-----需要关闭读端
5. 强化练习
a. 父子进程间通信,实现ps aux | grep bash
b. 兄弟进程间通信,实现ps aux | grep bash
a.父子间进程通信的实现思路
练习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.兄弟间进程通信的实现思路
练习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 胡云层 于南京