IPC之PIPE

  管道是一种只允许用在有亲属关系的进程间通信的方式,由函数pipe创建一个管道,read,write进行读写操作。

       #include <unistd.h>

       int pipe(int pipefd[2]);

参数pipefd[2]数组返回打开的读写描述符,pipefd[0]为读,pipefd[1]为写。

  第一个问题:文件描述符怎么会出现一个只能读,一个只能写呢?猜想是对一个文件打开了2次,一个以只读打开,一个以只写打开。使用fcntl来验证下:

       #include <unistd.h>
       #include <fcntl.h>

       int fcntl(int fd, int cmd, ... /* arg */ );
       F_GETFL (void)
              Get the file access mode and the file status flags; arg is ignored.

cmd为F_GETFL时,最后一个参数arg被忽略。测试代码:

 1 #include <sys/types.h>
 2 #include <sys/stat.h>
 3 #include <stdio.h>
 4 #include <fcntl.h>
 5 #include <signal.h>
 6 #include <unistd.h>
 7 #include <stdlib.h>
 8
 9 int main(void)
10 {
11     int flags;
12     int fd[2];
13
14     if (pipe(fd) < 0)
15     {
16         perror("pipe error");
17     }
18
19     flags = fcntl(fd[0], F_GETFL,0);
20     if ( flags < 0 )
21     {
22         perror("fcntl");
23         close(fd[0]);
24         close(fd[1]);
25     }
26     switch (flags & O_ACCMODE)
27     {
28         case O_RDONLY:
29             printf("read only\n");
30             break;
31
32         case O_WRONLY:
33             printf("write only\n");
34             break;
35
36         case O_RDWR:
37             printf("read write\n");
38             break;
39
40         default:
41             printf("unknown access mode\n");
42     }
43
44     flags = fcntl(fd[1], F_GETFL,0);
45     if ( flags < 0 )
46     {
47         perror("fcntl");
48         close(fd[0]);
49         close(fd[1]);
50     }
51     switch (flags & O_ACCMODE)
52     {
53         case O_RDONLY:
54             printf("read only\n");
55             break;
56
57         case O_WRONLY:
58             printf("write only\n");
59             break;
60
61         case O_RDWR:
62             printf("read write\n");
63             break;
64
65         default:
66             printf("unknown access mode\n");
67     }
68     close(fd[0]);
69     close(fd[1]);
70     exit(0);
71 }

运行结果:

read only
write only

与猜想相符。

  数据的流向:

从图中可以看出,进程可以以pipefd[1]写完,然后以pipefd[0]读,自己写自己读,这条数据流是通的。 验证:

 1 #include <sys/types.h>
 2 #include <sys/stat.h>
 3 #include <stdio.h>
 4 #include <fcntl.h>
 5 #include <signal.h>
 6 #include <unistd.h>
 7 #include <stdlib.h>
 8
 9 #define MAXLINE     4096
10 int main(void)
11 {
12     int flags;
13     int fd[2], n;
14     char buf[MAXLINE];
15     if (pipe(fd) < 0)
16     {
17         perror("pipe error");
18     }
19
20     n = write(fd[1], "hello world\n", MAXLINE);
21     if ( n < 0 )
22     {
23         perror("write");
24         goto end;
25     }
26     n = read(fd[0],buf, n);
27     if ( n < 0 )
28     {
29         perror("read");
30         goto end;
31     }
32     printf("read:%s\n",buf);
33
34 end:
35     close(fd[0]);
36     close(fd[1]);
37     exit(0);
38 }

输出:

read:hello world

  既然是进程间通信,那么管道在同一个进程中读写基本是没什么意义的,管道常用的方式是,先创建一个管道,然后fork,父子进程就共享了这个管道了。数据流向如图:

这样,管道的写端有2个进程操作,读端有2个进程操作。但是这样一来就出现了一个问题,假设父进程读,那么这个数据是它自己写进去的呢?还是子进程写进去的?无法区分。通常一个进程关闭它的读,另一个进程关闭它的写,这样,数据流向就只有一个方向了,数据来自谁就显而易见了。如图:

测试代码:

 1 #include <sys/types.h>
 2 #include <sys/stat.h>
 3 #include <stdio.h>
 4 #include <fcntl.h>
 5 #include <signal.h>
 6 #include <unistd.h>
 7 #include <stdlib.h>
 8 #include <string.h>
 9
10 #define MAXLINE     4096
11
12 int main(void)
13 {
14     int n;
15     int fd[2];
16     pid_t pid;
17     char line[MAXLINE];
18
19     if (pipe(fd) < 0)
20         perror("pipe error");
21     if ((pid = fork()) < 0)
22     {
23         perror("fork error");
24     }
25     else if (pid > 0)          /* parent */
26     {
27         close(fd[0]);
28         write(fd[1], "hello world\n", 12);
29     }
30     else                      /* child */
31     {
32         close(fd[1]);
33         n = read(fd[0], line, MAXLINE);
34         write(STDOUT_FILENO, line, n);
35     }
36     exit(0);
37 }

结果:

hello world
时间: 2024-12-18 20:50:17

IPC之PIPE的相关文章

Unix IPC之pipe

pipe创建函数: #include <unistd.h> /* 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. */ int pipe (int

multiprocessing在python中的高级应用-IPC 之 Pipe

作为使用队列的另一种形式,还可以使用管道在进程回见执行消息传递. Pipe( [ duplex]) 在进程之间创建一条管道,并返回元组(conn1,conn2),其中conn1和conn2是表示管道两端的Connection对象.默认情况下,管道是双向的.如果将duplex置为False,conn1只能用于接收,而conn2只能用于发送.必须在创建和启动使用管道的Process对象之前调用Pipe()方法. Pipe()方法返回的Connection对象的实例c具有以下方法和属性. c.clos

【APUE】Chapter16 Network IPC: Sockets &amp; makefile写法学习

16.1 Introduction Chapter15讲的是同一个machine之间不同进程的通信,这一章内容是不同machine之间通过network通信,切入点是socket. 16.2 Socket Descriptors socket抽象上是一个communication endpoint,具体就是一个int型变量.生成socket的函数如下: int socket(int domain, int type, int protocol) 函数有点儿类似open,即打开一个socket d

CVE-2017-7494 Linux Samba named pipe file Open Vul Lead to DLL Execution

catalogue 1. 漏洞复现 2. 漏洞代码原理分析 3. 漏洞利用前提 4. 临时缓解 && 修复手段 1. 漏洞复现 1. SMB登录上去 2. 枚举共享目录,得到共享目录/文件列表,匿名IPC$将会被跳过 3. 从中过滤目录,检测是否可写(通过创建一个.txt方式实现) 4. 生成一个随机8位的so文件名,并将paylaod写入so中 5. 最后一步,连接到\\192.168.206.128\\IPC$,在smb登录状态下,创建/打开一个named pipe 0x1: POC1

Linux进程间通信 --- IPC机制(转)

在linux下的多个进程间的通信机制叫做IPC(Inter-Process Communication),它是多个进程之间相互沟通的一种方法.在linux下有多种进程间通信的方法:半双工管道.命名管道.消息队列.信号.信号量.共享内存.内存映射文件,套接字等等.使用这些机制可以为linux下的网络服务器开发提供灵活而又坚固的框架. 1. 管道 (PIPE)    管道实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机.一个进程在向管道写入数据后,另

协议适配器错误的问题

今天遭遇ORA-12560: TNS: 协议适配器错误的问题,经过一番努力问题已经解决,与大家共享. 造成ORA-12560: TNS: 协议适配器错误的问题的原因有三个: 1.监听服务没有起起来.windows平台个一如下操作:开始---程序---管理工具---服务,打开服务面板, 启动oraclehome92TNSlistener服务. 2.database instance没有起起来.windows平台如下操作:开始---程序---管理工具---服务,打开服务 面板,启动oracleser

解决PL/SQL Developer连接数据库时出现 “ORA-12541:TNS:无监听程序”错误

在用PL/SQL Developer连接数据库时出现“ORA-12541:TNS:无监听程序”错误. 1.检查listener.log日志发现下面错误:TNSLSNR for 32-bit Windows: Version 10.2.0.1.0 - Production on 20-9月 -2008 10:25:26 Copyright (c) 1991, 2005, Oracle. All rights reserved. 系统参数文件为D:/oracle/product/10.2.0/db_

Oracle listener lsnrctl

lsnrctl(Listener Control)是一家SQL*Net具,用于控制数据库listener,此工具提供了控制命令listener开端.停止,查看listener状态,更改listener配置参数. lsnrctl简介 命令行中输入lsnrctl,你将得到: C:\Documents and Settings\Administrator>lsnrctl LSNRCTL for 32-bit Windows: Version 10.2.0.1.0 - Production on 26-

管道和信号的简单用法

2015.3.3星期二 阴天 IPC:进程间通信pipe:无名管道:只能用于具有亲缘关系的进程之间fifo: 有名管道:可以使互不相关的两个进程互相通信,有名管道可以通过路径名来指出,并且在文件系统中可见,通过文件io操作,不支持lseek() 管道创建: 无名:调用pipe();有名管道:1.mkfifo(),2.open 信号的处理:有一个阶段:“革命的前夜” 实现进程间通信,用系统调用pipe()建立一个管道,两个子进程分别向管道中各写一句话,父进程从管道中读出来,并显示.下面的代码有很多