linux应用编程学习(5)管道

第5类 管道通讯编程类
一、
通讯目的
1、数据传输
一个进程需要将数据发送给另一个进程。
2、资源共享
多个进程之间共享同样的资源。
3、通知事件
一个进程需要向另一个/组进程发送消息,通知它们发生了某事件。
4、进程控制
有些进程希望完全控制另一个进程的执行(如Debug进程),此时
控制进程希望能够拦截另一个进程的所有操作,并能够及时知道它
的状态改变。

二、通讯的发展
linux进程通信( IPC:interprocess comnunication),由UNIX进程间通信、基于System V进程间通信、POSIX进程间通信几部分发展而来的。
POSIX:(Portable Operating System Interface)表示可移植操作系统接口,用来提高可移植性。

三、Linux 通信方式
1、无名管道(pipe):数据传输
2、有名管道(FIFO):数据传输
3、信号(signal):事件通知
4、消息队列
5、共享内存
6、信号量:资源共享
7、套接字(socket)
四、 无名管带只能用于父进程和子进程通信,有名管道可用于运行同一系统中的任意两个进程间的通信。
1)管道通信是单向的,有固定的读端和写端
2)数据被进程从管道读出后,在管道中该(取)数据就不存在了。
3)当进程去读取空管道的时候,进程会阻塞。(进程等待:读时空就等到写入、管道满了空出来才能写)
4)管道容量为64KB(#define PIPE_BUFFERS 16 include/linux/pipe_fs_i.h)

5.1 创建无名管道
5.1.1 函数名
pipe
5.1.2 函数原形
int pipe(int pipefd[2]);
5.1.3 函数功能
创建无名管道
5.1.4 所属头文件
unistd . h
5.1.5 返回值
成功:0    失败:-1
5.1.6 参数说明
Pipefd[2]:pipefd[0]指向读端末尾
Pipefd[1]指向写端末尾

创建无名管道, 并用于父子进程通讯
  1. #include <unistd.h>
  2. #include <stdio.h>

  3. void main()
  4. {
  5.     int pipefd[2];
  6.     int ret;
  7.     pid_t pid;
  8.     char buf[20];
  9.     
  10.     /*创建管道*/
  11.     ret = pipe(pipefd);
  12.     if(ret == -1)
  13.     {
  14.         printf("creat pipe failed.\n");
  15.         return;
  16.     }
  17.     
  18.     pid = fork();
  19.     if(pid > 0)
  20.     {
  21.         /*父进程写入数据*/
  22.         write(pipefd[1], "Hello", 6);
  23.         wait();
  24.         close(pipefd[1]);
  25.         exit(0);
  26.     }
  27.     else if(pid == 0)
  28.     {
  29.         /*子进程读取数据*/
  30.         if(read(pipefd[0], buf, 6) > 0)
  31.              printf("read buf is %s.\n",buf);
  32.         exit(0);
  33.     }
  34.     else
  35.     {
  36.         printf("creat process failed.\n");
  37.         return;
  38.     }

  39. }

5.2 创建有名管道
5.2.1 函数名
mkfifo
5.2.2 函数原形
int mkfifo(const char* pathname, mode_t mode);  
5.2.3 函数功能
创建有名管道
5.2.4 所属头文件
sys/types.h  sys/stat.h
5.2.5 返回值
success:0  error:-1
5.2.6 参数说明
pathname:要创建的fifo文件名
mode:fifo文件创建的标志权限

5.3 删除有名管道
5.3.1 函数名
unlink
5.3.2 函数原形
int unlink(const char *pathname);
5.3.3 函数功能
删除文件
5.3.4 所属头文件
stdio.h
5.3.5 返回值
success:0
error:-1
5.3.6 参数说明
pathname:用来指明要删除的文件名字(含路径)

fifo-write.c
  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <fcntl.h>
  4. #include <stdio.h>
  5. #include <unistd.h>

  6. int main()
  7. {
  8.     int fd;

  9.     mkfifo("/tmp/myfifo",0666);

  10.     fd = open("/tmp/myfifo",O_WRONLY);

  11.     write(fd,"Hello World",12);

  12.     close(fd);
  13.     return 0;
  14. }
fifo-read.c
  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <fcntl.h>
  4. #include <unistd.h>
  5. #include <stdio.h>

  6. int main()
  7. {
  8.     int fd;
  9.     char buf[20];

  10.     fd = open("/tmp/myfifo",O_RDONLY);

  11.     read(fd,buf,15);
  12.     printf("read myfifo is %s.\n",buf);

  13.     close(fd);
  14.     unlink("/tmp/myfifo");
  15.     return 0;
  16. }

fifo在写入后如果没有被读取,进程会被阻塞直到被读取后结束。

http://blog.csdn.net/nodeathphoenix/article/details/23357453
一、对于FIFO,需要open去打开FIFO的读端或是写端的描述符。
1> 如果open的时候没有指定O_NONBLOCK标志,且open的是读端时
   如果不存在此FIFO的已经打开的写端时,open会一直阻塞到有FIFO的写端打开;
   如果已经存在此FIFO的打开的写端时,open会直接成功返回。

2> 如果open的时候没有指定O_NONBLOCK标志,且open的是写端时
   如果不存在此FIFO的已经打开的读端时,open会一直阻塞到有FIFO的读端打开;
   如果已经存在此FIFO的打开的读端时,open会直接成功返回。

二、从FIFO或者空管道读写
 1> read时,读端fd没有指定O_NONBLOCK标志
    如果存在此FIFO或管道的已经打开的写端时,阻塞到FIFO或管道中有数据或者FIFO或管道的已经打开的写端全部被关闭为止。
    如果不存在此FIFO或管道的已经打开的写端时,read返回0;
 2> write时, 同read差不多,就不详述了。
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(562) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
1. 实验目的 1) 加深对进程概念的理解,明确进程和程序的区别。 2) 进一步认识并发执行的实质。 3) 分析进程争用资源的现象,学习解决进程互斥的方法。 4) 学习解决进程同步的方法。 5) 了解Linux系统中进程通信的基本原理。   进程是操作系统中最重要的概念,贯穿始终,也是学习现代操作系统的关键。通过本次实验,要求理解进程的实质和进程管理的机制。在Linux系统下实现进程从创建到终止的全过程,从中体会进程的创建过程、父进程和子进程之间的关系、进程状态的变化、进程之间的互斥、同步机制、进程调度的原理和以管道为代表的进程间的通信方式的实现。 2. 内容及要求:   这是一个设计型实验,要求自行编制程序。   使用系统调用pipe()建立一条管道,两个子进程分别向管道写一句话:   Child process1 is sending a message!   Child process2 is sending a message!   父进程从管道读出来自两个子进程的信息,显示在屏幕上。   要求: 1) 父进程先接收子进程1发来的消息,然后再接收子进程2发来的消息。 2) 实现管道的互斥使用,当一个子进程正在对管道进行写操作时,另一子进程必须等待。使用系统调用lockf(fd[1],1,0)实现对管道的加锁操作,用lockf(fd[1],0,0)解除对管道的锁定。 3) 实现父子进程的同步,当子进程把数据写入管道后,便去睡眠等待;当父进程试图从一空管道中读取数据时,也应等待,直到子进程将数据写入管道后,才将其唤醒。 3.相关的系统调用 1) fork() 用于创一个子进程。 格式:int fork(); 返回值:在子进程中返回0;在父进程中返回所创建的子进程的ID值;当返回-1时,创建失败。 2) wait() 常用来控制父进程与子进程的同步。 在父进程中调用wait(),则父进程被阻塞,进入等待队列,等待子进程结束。当子进程结束时,父进程从wait()返回继续执行原来的程序。 返回值:大于0时,为子进程的ID值;等于-1时,调用失败。 3) exit() 是进程结束时最常调用的。 格式:void exit( int status); 其中,status为进程结束状态。 4) pipe() 用于创建一个管道 格式:pipe(int fd); 其中fd是一个由两个数组元素fd[0]和fd[1]组成的整型数组,fd[0]是管道的读端口,用于从管道读出数据,fd[1] 是管道的写端口,用于向管道写入数据。 返回值:0 调用成功;-1 调用失败。 5) sleep() 调用进程睡眠若干时间,之后唤醒。 格式:sleep(int t); 其中t为睡眠时间。 6) lockf() 用于对互斥资源加锁和解锁。在本实验中,该调用的格式为: lockf(fd[1],1,0);/* 表示对管道的写入端口加锁。 lockf(fd[1],0,0);/* 表示对管道的写入端口解锁。 7) write(fd[1],String,Length) 将字符串String的内容写入管道的写入口。 8) read(fd[0],String,Length) 从管道的读入口读出信息放入字符串String中。 4.程序流程 父进程: 1) 创建管道; 2) 创建子进程1; 3) 创建子进程2; 4) 等待从管道中读出子进程1写入的数据,并显示在屏幕上; 5) 等待从管道中读出子进程2写入的数据,并显示在屏幕上; 6) 退出。 子进程: 1) 将管道的写入口加锁; 2) 将信息“Child process n is sending message!”输入到变量OutPipe中,n=1,2; 3) 将OutPipe中信息写入管道; 4) 睡眠等待; 5) 将管道的写入口解锁; 6) 退出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

习惯就好zz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值