UNIX/Linux 是多任务的操作系统,通过多个进程分别处理不同事务来实现,如果多个进程要进行协同工作或者争用同一个资源时,互相之间的通讯就很有必要了
进程间通信,Inter process communication,简称 IPC ,在 UNIX/Linux 下主要有以下几种方式:
这里分享一下我在学习进程通讯过程中的笔记和心得
管道是 UNIX 系统 IPC 的最古老形式,所有 UNIX 系统都提供此种通信机制,但是管道有以下两种局限性
尽管有这两种局限性,半双工管道仍然是最常用的IPC形式
Tip: 每当在管道中键入一个命令序列,让shell执行时,shell都会为每一条命令单独创建一个进程,然后用管道将前一条命令进程的标准输出与后一条命令的标准输入相连接,管道是通过调用 pipe 函数创建的
下面通过一个例子,演示一下pipe管道的使用方法
创建一个从父进程到子进程的管道,并且父进程经由该管道向子进程传送数据
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#define MAX 1024
int main()
{
pid_t pid=0;
int res=-1,rb=0,wb=0,fd[2]; //定义一个整型数组来存放pipe函数的返回值,即管道的文件描述符
char buf[MAX]; //用于临时存放数据
memset(buf,0,sizeof(buf)); //置空缓存
if(0 > pipe(fd)) //创建管道,失败则报错
{
perror("pipe");
return res;
}
pid=fork();
if(0 == pid) //如果在子进程中
{
close(fd[1]); //关闭写端
printf("this is child, pid is :%d, my father pid is %d\n",getpid(),getppid());
if (0 > (rb=read(fd[0],buf,MAX))) //从管道的读端读出数据放到buf中
{
perror("read");
return res;
}
printf("pipe(%d):'%s': %d\n",fd[0],buf,rb); //将读端的文件描述与buf的内容进行打印
close(fd[0]);
}
else if (0 < pid) //如果在父亲进程中
{
close(fd[0]); //关闭读端
printf("this is the father process, my pid is :%d, child process pid is %d\n",getpid(),pid);
sprintf(buf,"pipe(%d)(%s)",fd[1],"hello pipe"); //将写端的文件描述符存到buf中,并且写入一段信息
if (0 > (wb=write(fd[1],buf,MAX))) //将buf中的内容写到管道中
{
perror("write");
return res;
}
close(fd[1]);
}
else //fork 出错,则提醒
{
perror("fork");
return res;
}
res=0;
return res;
}
emacs@ubuntu:~/c$ alias gtc
alias gtc='gcc -Wall -g -o'
emacs@ubuntu:~/c$ gtc pipe.x pipe.c
emacs@ubuntu:~/c$ ./pipe.x
this is the father process, my pid is :10337, child process pid is 10338
this is child, pid is :10338, my father pid is 10337
pipe(3):'pipe(4)(hello pipe)': 1024
emacs@ubuntu:~/c$
编译执行过程中没有报错,从结果来看,符合预期
Note: 有时子进程的输出中显示父进程为1,原因是父进程先于子进程退出,这样子进程就变成了孤儿进程,孤儿进程会被init进程收养,所以父进程号就变成了1
emacs@ubuntu:~/c$ ./pipe.x
this is the father process, my pid is :10323, child process pid is 10324
emacs@ubuntu:~/c$ this is child, pid is :10324, my father pid is 1
pipe(3):'pipe(4)(hello pipe)': 1024
emacs@ubuntu:~/c$
unistd.h
中有 pipe 函数的原型声明
/* Create a one-way communication channel (pipe).
If successful, two file descriptors are stored in PIPEDES;
bytes written on PIPEDES[1] can be read from PIPEDES[0].
Returns 0 if successful, -1 if not. */
extern int pipe (int __pipedes[2]) __THROW __wur;
stdio.h
中有 sprintf 的函数原型声明
/* Write formatted output to S. */
extern int sprintf (char *__restrict __s,
__const char *__restrict __format, ...) __THROW;
以下函数可以进行无名管道的创建
通过各方面资料弄懂其参数的意义和返回值的类型,是熟练掌握的基础
原文地址
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。