Linux 进程间通信(一)(经典IPC:管道、FIFO)

管道

管道是Unix系统IPC的最古老方式,有两种局限性:

(1)   历史上它们是半双工的(即数据只能在一个方向上流动),虽然现在某些系统提供了全双工管道,但是为了可移植性,不要抱有绝对的全双工假设。

(2)   管道只能在具有公共祖先的两个进程之间使用(一般都是用于父子进程之间)。

管道是通过调用pipe函数创建的:


#include <unistd.h>

int pipe(int fd[2]);

返回值:成功,返回0;失败,返回-1

说明:

fd返回两个文件描述符:fd[0]用于读,fd[1]用于写,fd[1]的输出刚好是fd[0]的输入。

即shell为每一条命令单独创建一个进程,然后管道将前一条命令的标准输出与后一条命令的标准输入相连接。

注:

POSIX.1允许实现支持全双工管道,对于这些实现,fd[0]和fd[1]以读/写方式打开。

如下给出了两种描绘半双工管道的方法,左图中管道的两端在一个进程中相互连接,右图中则强调数据需要通过内核在管道中流动:

管道通常在单个进程中没有太大用处,下图显示了父子进程之间的管道:进程先调用pipe,接着调用fork,从而创建从父进程到子进程的IPC管道

fork之后具体要做什么取决于我们想要的数据流的方向。对于从父进程到子进程的管道,父进程关闭管道的读端(fd[0]),子进程关闭管道的写端(fd[1]):

当管道的一端被关闭后,下列两条规则起作用:

(1)   当read一个写端已被关闭的管道时,在所有数据都被读取后,read返回0,表示文件结束。

(2)   当write一个读端已被关闭的管道时,则产生信号SIGPIPE,如果忽略该信号或者捕捉该信号并从其处理程序返回,则write返回-1,errno设置为EPIPE。

如下为管道程序实例:

实例一:创建一个从父进程到子进程的管道,并且父进程经由该管道向子进程传送数据:

 1 [[email protected] ipc]# cat pipe1.c
 2 #include <unistd.h>
 3 #include <stdio.h>
 4
 5 #define MAXLINE 1024
 6
 7 int main(void)
 8 {
 9         int             n;
10         int             fd[2];
11         pid_t   pid;
12         char    line[MAXLINE];
13
14         if (pipe(fd) < 0)
15                 printf("pipe error\n");
16         if ((pid = fork()) < 0) {
17                 printf("fork error\n");
18         } else if (pid > 0) {           /* parent */
19                 close(fd[0]);
20                 write(fd[1], "hello world\n", 12);              /* write data to fd[1] */
21         } else {                                        /* child */
22                 close(fd[1]);
23                 n = read(fd[0], line, MAXLINE);                 /* read data from fd[0] */
24                 write(STDOUT_FILENO, line, n);                  /* write data to standard output */
25         }
26
27         return (0);
28 }
29
30 [[email protected] ipc]# ./pipe1
31 [[email protected] ipc]# hello world
32
33 [[email protected] ipc]#

实例二:编写一个程序,其功能是每次一页地显示已产生的输出。为了避免先将所有数据写到一个临时文件中,然后再调用系统中有关程序显示该文件,我们希望通过管道将输出直接送到分页程序。为此,先创建一个管道,fork一个子进程,使子进程的标准输入成为管道的读端,然后调用exec,执行分页程序:(说明点:1. 在调用fork之前,先创建一个管道。调用fork之后,父进程关闭读端,子进程关闭写端,然后子进程调用dup2,使其标准输入成为管道的读端。当执行分页程序时,其标准输入就是管道的读端了; 2. 我们使用环境变量PAGER来获得用户分页程序名,如果没有成功,则使用系统默认值,这是环境变量的常见用法。)

  1 [[email protected] ipc]# cat pipe2.c
  2 #include <unistd.h>
  3 #include <sys/wait.h>
  4 #include <stdio.h>
  5
  6 #define DEF_PAGER       "/bin/more"             /* default pager program */
  7 #define MAXLINE 1024
  8
  9 int main(int argc, char *argv[])
 10 {
 11         int             n;
 12         int             fd[2];
 13         pid_t   pid;
 14         char    *pager, *argv0;
 15         char    line[MAXLINE];
 16         FILE    *fp;
 17
 18         if (argc != 2)
 19         {
 20                 printf("usage: a.out <pathname>\n");
 21                 return (-1);
 22         }
 23
 24         if ((fp = fopen(argv[1], "r")) == NULL)
 25                 printf("can‘t open %s\n", argv[1]);
 26         if (pipe(fd) < 0)
 27                 printf("pipe error\n");
 28
 29         if ((pid = fork()) < 0) {
 30                 printf("fork error\n");
 31         } else if (pid > 0) {                                             /* parent */
 32                 close(fd[0]);           /* close read end */
 33
 34                 /* parent copies argv[1] to pipe */
 35                 while (fgets(line, MAXLINE, fp) != NULL) {
 36                         n = strlen(line);
 37                         if (write(fd[1], line, n) != n)
 38                                 printf("write error to pipe\n");
 39                 }
 40                 if (ferror(fp))
 41                         printf("fgets error\n");
 42
 43                 close(fd[1]);   /* close write end of pipe for reader */
 44
 45                 if (waitpid(pid, NULL, 0) < 0)
 46                         printf("waitpid error\n");
 47                 return (0);
 48         } else {                                                          /* child */
 49                 close(fd[1]);   /* close write end */
 50                 if (fd[0] != STDIN_FILENO) {
 51                         if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
 52                                 printf("dup2 error to stdin\n");
 53                         close(fd[0]);   /* don‘t need this after dup2 */
 54                 }
 55
 56                 /* get arguments for execl() */
 57                 if ((pager = getenv("PAGER")) == NULL)
 58                         pager = DEF_PAGER;
 59                 if ((argv0 = strrchr(pager, ‘/‘)) != NULL)
 60                         argv0++;                /* step past rightmost slash */
 61                 else
 62                         argv0 = pager;  /* no slash in pager */
 63
 64                 if (execl(pager, argv0, (char *)0) < 0)
 65                         printf("execl error for %s\n", pager);
 66         }
 67         return (0);
 68 }
 69 [[email protected] ipc]# ./pipe2 pipe2.c
 70 #include <unistd.h>
 71 #include <sys/wait.h>
 72 #include <stdio.h>
 73
 74 #define DEF_PAGER       "/bin/more"             /* default pager program */
 75 #define MAXLINE 1024
 76
 77 int main(int argc, char *argv[])
 78 {
 79         int             n;
 80         int             fd[2];
 81         pid_t   pid;
 82         char    *pager, *argv0;
 83         char    line[MAXLINE];
 84         FILE    *fp;
 85
 86         if (argc != 2)
 87         {
 88                 printf("usage: a.out <pathname>\n");
 89                 return (-1);
 90         }
 91
 92         if ((fp = fopen(argv[1], "r")) == NULL)
 93                 printf("can‘t open %s\n", argv[1]);
 94         if (pipe(fd) < 0)
 95                 printf("pipe error\n");
 96
 97         if ((pid = fork()) < 0) {
 98                 printf("fork error\n");
 99         } else if (pid > 0) {                                             /* parent */
100                 close(fd[0]);           /* close read end */
101
102                 /* parent copies argv[1] to pipe */
103                 while (fgets(line, MAXLINE, fp) != NULL) {
104 --More--

实例三:父子进程同步函数的管道实现:TELL_WAIT、TELL_PARENT、TELL_CHILD、WAIT_PARENT、WAIT_CHILD:(说明点:父进程在调用TELL_CHILD时,经由上一个管道写一个字符“p”,子进程在调用TELL_PARENT时,经由下一个管道写一个字符“c”,相应的WAIT_XXX函数调用read读一个字符,没有读到字符时则阻塞)

 1 static int    pfd1[2], pfd2[2];
 2
 3 void TELL_WAIT(void)
 4 {
 5     if (pipe(pfd1) < 0 || pipe(pfd2) < 0)
 6         printf("pipe error\n");
 7 }
 8
 9 void TELL_PARENT(pid_t pid)
10 {
11     if (write(pfd2[1], "c", 1) != 1)
12         printf("write error\n");
13 }
14
15 void WAIT_PARENT(void)
16 {
17     char    c;
18
19     if (read(pfd1[0], &c, 1) != 1)
20         printf("read error\n");
21
22     if (c != ‘p‘)
23     {
24         printf("WAIT_PARENT: incorrect data\n");
25         return ;
26     }
27
28 }
29
30 void TELL_CHILD(pid_t pid)
31 {
32     if (write(pfd1[1], "p", 1) != 1)
33         printf("write error\n");
34 }
35
36 void WAIT_CHILD(void)
37 {
38     char    c;
39
40     if (read(pfd2[0], &c, 1) != 1)
41         printf("read error\n");
42
43     if (c != ‘c‘)
44     {
45         printf("WAIT_CHILD: incorrect data\n");
46         return ;
47     }
48 }

常见的操作是创建一个连接到另一个进程的管道,然后读其输出或向其输入端发送数据,为此,标准I/O库提供了两个函数popen和pclose。这两个函数的功能是:创建一个管道,fork一个子进程,关闭未使用的管道端,然后执行一个shell运行命令,等待命令终止(使用popen可以减少代码编写量)。


#include <stdio.h>

FILE* popen(const char* cmdstring, const char* type);

返回值:成功,返回文件指针;失败,返回NULL

int pclose(FILE* fp);

返回值:成功,返回cmdstring的终止状态;失败,返回-1

说明:

函数popen先执行fork,然后调用exec执行cmdstring,并且返回一个标准I/O文件指针。如果type是r,则文件指针连接到cmdstring的标准输出;如果type是w,则文件指针连接到cmdstring的标准输入,见下图:

pclose函数关闭标准I/O流,等待命令终止,然后返回shell的终止状态。

cmdstring由Bourne shell以下列方式执行:sh –c cmdstring

shell命令${PAGER:-more}的意思是:如果shell变量PAGER已经定义,且其值非空,则使用其值,否则使用字符串more。利用popen函数重写实例二

 1 [[email protected] ipc]# cat pipe3.c
 2 #include <stdio.h>
 3 #include <sys/wait.h>
 4
 5 #define MAXLINE 1024
 6 #define PAGER   "${PAGER:-more}" /* environment variable, or default */
 7
 8 int main(int argc, char *argv[])
 9 {
10         char    line[MAXLINE];
11         FILE    *fpin, *fpout;
12
13         if (argc != 2)
14         {
15                 printf("usage: a.out <pathname>\n");
16                 return (-1);
17         }
18
19         if ((fpin = fopen(argv[1], "r")) == NULL)
20                 printf("can‘t open %s\n", argv[1]);
21
22         if ((fpout = popen(PAGER, "w")) == NULL)
23                 printf("popen error\n");
24
25         /* copy argv[1] to pager */
26         while (fgets(line, MAXLINE, fpin) != NULL) {
27                 if (fputs(line, fpout) == EOF)
28                         printf("fputs error to pipe\n");
29         }
30         if (ferror(fpin))
31                 printf("fgets error\n");
32         if (pclose(fpout) == -1)
33                 printf("pclose error\n");
34
35         return (0);
36 }
37 [[email protected] ipc]# ./pipe3 pipe2.c
38 #include <unistd.h>
39 #include <sys/wait.h>
40 #include <stdio.h>
41
42 #define DEF_PAGER       "/bin/more"             /* default pager program */
43 #define MAXLINE 1024
44
45 int main(int argc, char *argv[])
46 {
47         int             n;
48         int             fd[2];
49         pid_t   pid;
50         char    *pager, *argv0;
51         char    line[MAXLINE];
52         FILE    *fp;
53
54         if (argc != 2)
55         {
56                 printf("usage: a.out <pathname>\n");
57                 return (-1);
58         }
59
60         if ((fp = fopen(argv[1], "r")) == NULL)
61                 printf("can‘t open %s\n", argv[1]);
62         if (pipe(fd) < 0)
63                 printf("pipe error\n");
64
65         if ((pid = fork()) < 0) {
66                 printf("fork error\n");
67         } else if (pid > 0) {                                             /* parent */
68                 close(fd[0]);           /* close read end */
69
70                 /* parent copies argv[1] to pipe */
71                 while (fgets(line, MAXLINE, fp) != NULL) {
72 --More--

协同进程:

当一个进程既要产生某个程序的输入,又读取该程序的输出时,它就变成了协同进程(coprocess)。协同进程通常在shell后台运行,其标准输入和标准输出通过管道连接到另一个程序。popen只提供连接到另一个进程的标准输入或标准输出的一个单向管道,而协同进程则有连接到另一个进程的两个单向管道:一个连接到其标准输入,另一个则来自其标准输出。

实例:从标准输入读取两个数,计算它们的和,然后将和写至其标准输出。

 1 [[email protected] ipc]# cat coprocess.c
 2 #include <unistd.h>
 3 #include <stdio.h>
 4
 5 #define MAXLINE 1024
 6
 7 int main(void)
 8 {
 9         int             n, int1, int2;
10         char    line[MAXLINE];
11
12         while ((n = read(STDIN_FILENO, line, MAXLINE)) > 0) {
13                 line[n] = 0;            /* null terminate */
14                 if (sscanf(line, "%d%d", &int1, &int2) == 2) {
15                         sprintf(line, "%d\n", int1 + int2);
16                         n = strlen(line);
17                         if (write(STDOUT_FILENO, line, n) != n)
18                                 printf("write error\n");
19                 } else {
20                         if (write(STDOUT_FILENO, "invalid args\n", 13) != 13)
21                                 printf("write error\n");
22                 }
23         }
24
25         return (0);
26 }
27
28 [[email protected] ipc]# ./coprocess
29 1 2
30 3
31 10 20
32 30
33 100 200
34 300
35 ^C
36 [[email protected] ipc]#

实例:将上述程序编译成为add2协同进程,然后下列程序创建了两个管道,父进程、子进程各自关闭了它们不需要的管道端,必须使用两个管道:一个用作协同进程的标准输入,另一个用作它的标准输出。然后子进程调用dup2使管道描述符移至其标准输入和标准输出,最后调用了excel执行add2:

 1 [[email protected] ipc]# gcc coprocess.c -o add2
 2 [[email protected] ipc]# cat coprocess2.c
 3 #include <unistd.h>
 4 #include <signal.h>
 5 #include <stdio.h>
 6
 7 #define MAXLINE 1024
 8
 9 static void     sig_pipe(int);          /* our signal handler */
10
11 int main(void)
12 {
13         int             n, fd1[2], fd2[2];
14         pid_t   pid;
15         char    line[MAXLINE];
16
17         if (signal(SIGPIPE, sig_pipe) == SIG_ERR)
18                 printf("signal error\n");
19
20         if (pipe(fd1) < 0 || pipe(fd2) < 0)
21                 printf("pipe error\n");
22
23         if ((pid = fork()) < 0) {
24                 printf("fork error\n");
25         } else if (pid > 0) {                                             /* parent */
26                 close(fd1[0]);
27                 close(fd2[1]);
28
29                 while (fgets(line, MAXLINE, stdin) != NULL) {
30                         n = strlen(line);
31                         if (write(fd1[1], line, n) != n)
32                                 printf("write error to pipe\n");
33                         if ((n = read(fd2[0], line, MAXLINE)) < 0)
34                                 printf("read error from pipe\n");
35                         if (n == 0) {
36                                 printf("child closed pipe\n");
37                                 break;
38                         }
39                         line[n] = 0;    /* null terminate */
40                         if (fputs(line, stdout) == EOF)
41                                 printf("fputs error\n");
42                 }
43
44                 if (ferror(stdin))
45                         printf("fgets error on stdin\n");
46                 exit(0);
47         } else {                                                          /* child */
48                 close(fd1[1]);
49                 close(fd2[0]);
50                 if (fd1[0] != STDIN_FILENO) {
51                         if (dup2(fd1[0], STDIN_FILENO) != STDIN_FILENO)
52                                 printf("dup2 error to stdin\n");
53                         close(fd1[0]);
54                 }
55
56                 if (fd2[1] != STDOUT_FILENO) {
57                         if (dup2(fd2[1], STDOUT_FILENO) != STDOUT_FILENO)
58                                 printf("dup2 error to stdout\n");
59                         close(fd2[1]);
60                 }
61                 if (execl("./add2", "add2", (char *)0) < 0)
62                         printf("execl error\n");
63         }
64         exit(0);
65 }
66
67 static void sig_pipe(int signo)
68 {
69         printf("SIGPIPE caught\n");
70         exit(1);
71 }
72
73 [[email protected] ipc]# ./coprocess2
74 100 50
75 150
76 100 500
77 600

FIFO

FIFO有时被称为命名管道,未命名的管道只能在两个相关的进程之间使用,而且这两个相关的进程还要有一个共同的祖先进程。但是,通过FIFO,不相关的进程之间也能交换数据。

使用如下函数创建FIFO:


#include <sys/stat.h>

int mkfifo(const char* path, mode_t mode);

int mkfifoat(int fd, const char* path, mode_t mode);

返回值:成功,返回0;失败,返回-1

说明:

mkfifoat与mkfifo相似,像之前其他*at系列函数一样,有3种情形:

(1)   如果path参数指定了绝对路径名,则fd被忽略,此时mkfifoat和mkfifo一样。

(2)   如果path参数指定了相对路径名,则fd参数是一个打开目录的有效文件描述符,路径名和目录有关。

(3)   如果path参数指定了相对路径名,并且fd参数指定了AT_FDCWD,则路径名以当前目录开始,mkfifoat和mkfifo类似。

当我们使用mkfifo或者mkfifoat函数创建FIFO时,要用open打开,确是,正常的I/O函数(如close、read、write、unlink)都需要FIFO。当open一个FIFO时,非阻塞标志(O_NONBLOCK)会产生如下影响:

(1)   没有指定O_NONBLOCK时,只读open要阻塞到某个其他进程为写而打开这个FIFO为止。类似地,只写open要阻塞到某个其他进程为读而打开这个FIFO为止。

(2)   如果指定了P_NONBLOCK,则只读open立即返回。但是,如果没有进程为读而打开这个FIFO,那么只写open将返回-1,并将errno设置为ENXIO。

一个给定的FIFO有多个写进程是很常见的,这就意味着,如果不希望多个进程所写的数据交叉,则必须考虑原子写操作。和管道一样,常量PIPE_BUF说明了可被原子地写到FIFO的最大数据量。

FIFO主要有以下两种用途:

(1)   shell命令使用FIFO将数据从一条管道传送到另一条管道,无需创建中间临时文件。

实例:考虑这样一个过程,他需要对一个输入文件进行两次处理,示意图如下:

我们可以使用FIFO和tee命令如下处理:

mkfifo fifo1

prog3 < fifo1 &

prog1 < (输入文件) | tee fifo1 | prog2

执行流程如下:

(2)   客户进程-服务器进程应用程序中,FIFO用作汇聚点,在客户进程和服务器进程之间传递数据。

实例:有一个服务器进程,它与很多客户进程相关,每个客户进程都可将请求写到一个该服务器进程创建的FIFO中。由于该FIFO有多个写进程,因此客户进程每次发送给服务器的数据长度要小于PIPE_BUF字节,这样就能避免客户进程之间的写交叉。

但是这种类型的FIFO设计有问题,服务器如何回应各个客户进程呢?一种解决方法是,每个客户进程都在其请求中包含它的进程ID,然后服务器进程为每个客户进程创建一个FIFO,所使用的路径名是以客户进程的进程ID为基础的。例如,服务进程可以用名字/tmp/serv1.XXXXX创建FIFO,其中XXXXX被替换成客户进程的进程ID,如下图所示:

时间: 2024-07-31 09:01:30

Linux 进程间通信(一)(经典IPC:管道、FIFO)的相关文章

嵌入式 Linux进程间通信(六)——管道

嵌入式 Linux进程间通信(六)--管道 一.管道 管道是单向的.先进先出的.无结构的.固定大小的字节流.写进程在管道的尾端写入数据,读进程在管道的首端读出数据.数据读出后将从管道中移走,其它读进程都不能再读到这些数据.管道提供了简单的流控制机制.进程试图读空管道时,在有数据写入管道前,进程将一直阻塞:管道已经满时,进程再试图写管道,在其它进程从管道中移走数据之前,写进程将一直阻塞.管道存在于系统内核之中,管道只能用于具有亲缘关系进程间的通信.管道是半双工的,数据只能向一个方向流动:需要双方通

linux 进程间通信机制(IPC机制)- 管道

一,定义: 管道又可以分为无名管道和命名管道,两者的用途是不一样的. 无名管道PIPE:主要用于具有亲缘关系的进程之间的通信,无名管道的通信是单向的,只能由一段到另外一段:无名管道是临时性的,完成通信后将自动消失.一般采用先创建无名管道,再创建子进程,使子进程继承父进程的管道文件描述符,从而实现父子进程间的通信:在非亲缘关系管道之间,如果想利用无名管道进行通信,则需要借助另外的文件描述符传递机制. 有名管道FIFO:有名管道是一个实际存在的特殊文件,利用有名管道可以实现同主机任意进程之间的数据交

linux进程间通信之一:无名管道

无名管道是linux中管道通信的一种原始方法,有以下特征: 1.单工通信模式,具有固定的读端和写端: 2.管道可以看成是一种特殊的文件,对于它的读写可以使用普通的read(),write()等文件IO操作函数接口,但是它不属于任何文件系统,并且只存在与内存中: 3.只能用于具有亲缘关系的进程之间的通信: 4.通常使用时,首先创建一个管道,然后调用fork函数创建一个子进程,该子进程会继承父进程所创建的管道: 5.只有在管道的读端存在时,向管道写入数据才有意义,否则向管道写入的数据的进程将收到内核

Linux进程间通信(IPC)机制总览

Linux进程间通信 Ø  管道与消息队列 ü  匿名管道,命名管道 ü  消息队列 Ø  信号 ü  信号基础 ü  信号应用 Ø  锁与信号灯 ü  记录锁 ü  有名信号灯 ü  无名信号灯(基于内存的信号灯) Ø  共享内存 ü  共享内存介绍 ü  文件映射内存方式 ü  共享内存对象方式 为什么需要进程间通信 Ø  数据传输代表:管道 FIFO 消息队列 SOCKET Ø  事件通知代表:信号 Ø  分工协作代表:锁和信号灯 Ø  高效数据共享代表:共享内存 进程间通信主要分支及演进

嵌入式 Linux进程间通信(五)——进程间通信简介

嵌入式 Linux进程间通信(五)--进程间通信简介 一.进程间通信简介 Linux的进程通信方式基本上是从Unix平台上的进程通信方式继承而来的.在Unix发展过程中,贝尔实验室和BSD(加州大学伯克利分校的伯克利软件发布中心)是Unix发展的主要贡献者,但两者在进程间通信方面的侧重点有所不同.贝尔实验室对Unix早期的进程间通信方式进行了系统的改进和扩充,形成了 "system V IPC",通信进程局限在本地计算机内:BSD则跳过了进程通信局限在本地计算机的限制,形成了可以在计算

Linux环境编程之IPC进程间通信(四):管道和FIFO比较

系统加于管道和FIFO的唯一限制是: 1.OPEN_MAX 一个进程在任意时刻打开的最大描述符数.可以通过调用sysconf函数查询. 2.PIPE_BUF 可原子地写往一个管道或FIFO的最大数据量.Posix任务它是一个路径名变量,它的值可以随指定的路径名而变化,因为不同的路径名可以落在不同文件系统上,而这些文件系统可能有不同的特征.所以PIPE_BUF可通过pathconf函数取得. pipeconf.c #include <stdio.h> #include <stdlib.h&

Linux环境编程之IPC进程间通信(三):FIFO

管道是没有名字的,因此它只能在有亲缘关系的进程间使用,给管道加上名字,我们称之为有名管道FIFO,当然FIFO与管道之间不止有没有名字的区别,还有其他区别下面会提到.与管道类似的是,FIFO是一个单向(半双工)数据流.不同于管道的是,每个FIFO有一个路径名与之关联,从而允许无亲缘关系的进程之间访问同一个FIFO.FIFO是一种文件类型.stat结构成员st_mode的编码指明文件是否是FIFO类型,可以用S_ISFIFO宏对此进行测试. FIFO由mkfifo函数创建,它已经隐含指定了O_CR

Linux 进程间通信(一)(经典IPC:消息队列、信号量、共享存储)

有3种称作XSI IPC的IPC:消息队列.信号量.共享存储.这种类型的IPC有如下共同的特性. 每个内核中的IPC都用一个非负整数标志.标识符是IPC对象的内部名称,为了使多个合作进程能够在同一IPC对象上汇聚,需要提供一个外部命名方案.因此,将每个IPC对象都与一个键相关联,将这个键(key)作为该对象的外部名.这个键的数据类型是key_t,通常在头文件<sys/types.h>中被定义为长整型,该键由内核变换成标识符. 有3种方式可以使客户进程和服务器进程在同一IPC结构上汇聚: (1)

Linux环境编程之IPC进程间通信(二):管道

管道作为最古老的进程间通信方法,它有以下几个特点: 1.在所有的UNIX实现中都存在. 2.没有名字,因此只能由有亲缘关系的进程使用. 3.它由函数pipe创建,read和write函数访问,但只提供单路(单向)数据流. <span style="font-size:14px;">#include <unistd.h> int pipe(int fd[2]); 返回:若成功则为0,若出错则为-1</span> 经由参数fd返回两个文件描述符:fd[0