进程间通信实例
🌰管道
#include <unistd.h>
int pipe(int fd[2]);
//fd[0]是管道的读端,fd[1]是管道的写端,fd[1]的输出就是fd[0]输入
管道其实就是 内核中的一串缓存,往缓存中写&读实现进程通信,传输的是字节流
当然在一个进程内管道作用不是很大,主要发挥作用的场景就是多进程
我们可以通过fork创建子进程, 创建的子进程会复制父进程的文件描述符,那么两个进程就都有
fd[0] & fd[1]
了,那么就能往缓存中写(write),从缓存中读取(read)如果用
read
读取一个空管道,read
就会被阻塞直到管道中有数据,write
也是一样的如果fd[1]的引用计数为零,也就是没有写端了,再用
read
读就返回0(End Of File),如果fd[0]引用计数为零,没有读端了,再用write
就会引发SIGPIPE
信号。 关于信号的书建议看CSAPP,Lab可以看这里我们说管道是一个缓存,肯定要有容量的,
基本的管道应用实例
图片来源于小林图解系统
#include "csapp.c"
int main()
{
int n, fd[2];
pid_t pid;
char line[1024];
if (pipe(fd) < 0) { //绑定好管道
printf("pipe error");
}
if ((pid = fork()) < 0) {
printf("fork error");
}else if (pid > 0) {
close(fd[0]); //关掉读端
write(fd[1], "hello world\n", 12);
}else {
close(fd[1]); //关掉写端
n = read(fd[0], line, 1024);//从管道内读->line
write(STDOUT_FILENO, line, n);//将line中的打印(标准输出)
}
exit(0);
}
🌰dup函数
有时候我们需要将
标准输入
重定向到一个文件,或者将标准输出
重定向到网络连接太骚了这操作
#include <unistd.h>
int dup(int fd); //创建新描述符,新的与旧的fd共享同一个文件表项(也就是指向一个文件)
int dup2(int fd1, int fd2);//同dup差不多,返回第一个不小于fd2的整数
我们知道文件描述符号都是整数,因为有这一层抽象我们很轻松的描述文件
- 标准输入 0
- 标准输出 1
- 标准错误 2
使用样例
假设我们创建了一个Server
//
。。。。。。
//
int connfd = accept(sock, (struct sockaddr *)&client, &client_addrlength);
//创建了同Client的socket连接了
close(STDOUT_FILENO); //关闭标准输出 :1
dup(connfd); //使用系统最小可用描述符,那就是1了,那么就将socket同标准输出绑定了
printf("abcdefg\n"); //我们在标准输出输出的内容就会发送到client对应的socket
close (connfd);
//...