博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
13.无名管道通讯编程
阅读量:4677 次
发布时间:2019-06-09

本文共 4898 字,大约阅读时间需要 16 分钟。

13.无名管道通讯编程

 

1.进程间的通信:

Linux作为典型的多进程操作系统,进程与进程之间肯定需要信息交流,这就需要进程通信。

2.进程通信的目的:

    1.数据传输:一个进程需要将数据发送给另一个进程。

    2.资源共享:多个进程之间共享同样的资源。

    3.通知事件:一个进程需要向另一个/组进程发送信息,通知他们发生了某些事情。

    4.进程控制:有些进程希望完全控制另一个进程的执行,例如Debug进程。此时控制进程希望能够拦截另一个进程的所有操作,并能够及时知道他的状态改变。

 

3.通讯发展:

    Linux进程间通信(IPC:Interprocess Communication)由以下几个部分发展而来:

  1. UNIX进程间通信。
  2. 基于System V进程间通信
  3. POSIX进程间通信。

 

4.通讯发展-posix:

POSIX(Portable Operating System Interface)表示可移植操作系统接口。电气和电子工程师协会IEEE最初开发 POSIX 标准,是为了提高 UNIX 环境下应用程序的可移植性。然而,POSIX 并不局限于 UNIX,许多其它的操作系统,例如Microsoft Windows都支持POSIX 标准。

 

5.通讯方式:

Linux进程间通讯的主要方式有:

1、无名管道(pipe)

2、有名管道(FIFO)

3、信号(signal)

4、消息队列

5、共享内存

6、信号量

7、套接字(socket)

 

6.管道通信:

一个进程在管道的尾部写入数据,另一个进程从管道的头部读出数据。管道包括无名管道和有名管道两种,前者只能用于父进程和子进程间的通信,后者可用于运行于同一系统中的任意两个进程间的通信。

 

7.管道通信的特点:

1. 管道通讯是单向的,有固定的读端和写端。

2. 数据被进程从管道读出后,在管道中该数据就不存在了。

3. 当进程去读取空管道的时候,进程会阻塞。

4. 当进程往满管道写入数据时,进程会阻塞。

5. 管道容量为64KB

 

8.无名管道:

在Linux系统中,无名管道一旦创建完成后,操作无名管道等同于操作文件。无名管道的读端被视作一个文件,要读出无名管道的数据,需要找到读端文件;无名管道的写端也被视作一个文件,要往一个无名管道写数据,就是操作写端文件。

 

一、无名管道

在Linux系统中,无名管道一旦创建完成后,操作无名管道等同于操作文件。因此可以使用read,write,close等函数来访问无名管道。

 

 

 

 

 

 

无名管道:pipe

函数的原型:man 2 pile:

NAME

pipe, pipe2 - create pipe

 

SYNOPSIS

#include <unistd.h>

 

int pipe(int pipefd[2]);

 

#define _GNU_SOURCE

#include <unistd.h>

 

int pipe2(int pipefd[2], int flags);

 

DESCRIPTION

pipe() creates a pipe, a unidirectional data channel that can be used for

interprocess communication. The array pipefd is used to return two file

descriptors referring to the ends of the pipe. pipefd[0] refers to the read

end of the pipe. pipefd[1] refers to the write end of the pipe. Data written

to the write end of the pipe is buffered by the kernel until it is read from

the read end of the pipe. For further details, see pipe(7).

 

If flags is 0, then pipe2() is the same as pipe(). The following values can be

bitwise ORed in flags to obtain different behavior:

 

O_NONBLOCK Set the O_NONBLOCK file status flag on the two new open file

descriptions. Using this flag saves extra calls to fcntl(2) to

achieve the same result.

O_CLOEXEC Set the close-on-exec (FD_CLOEXEC) flag on the two new file

descriptors. See the description of the same flag in open(2) for

reasons why this may be useful.

 

RETURN VALUE

On success, zero is returned. On error, -1 is returned, and errno is set

appropriately.

 

ERRORS

EFAULT pipefd is not valid.

 

EINVAL (pipe2()) Invalid value in flags.

 

EMFILE Too many file descriptors are in use by the process.

 

ENFILE The system limit on the total number of open files has been reached.

 

VERSIONS

pipe2() was added to Linux in version 2.6.27; glibc support is available start-

ing with version 2.9.

 

CONFORMING TO

pipe(): POSIX.1-2001.

 

pipe2() is Linux-specific.

EXAMPLE

The following program creates a pipe, and then fork(2)s to create a child pro-

cess; the child inherits a duplicate set of file descriptors that refer to the

same pipe. After the fork(2), each process closes the descriptors that it

doesn't need for the pipe (see pipe(7)). The parent then writes the string

contained in the program's command-line argument to the pipe, and the child

reads this string a byte at a time from the pipe and echoes it on standard out-

put.

 

#include <sys/wait.h>

#include <assert.h>

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

 

int

main(int argc, char *argv[])

{

int pipefd[2];

pid_t cpid;

char buf;

 

assert(argc == 2);

 

if (pipe(pipefd) == -1) {

perror("pipe");

exit(EXIT_FAILURE);

}

 

cpid = fork();

if (cpid == -1) {

perror("fork");

exit(EXIT_FAILURE);

}

 

if (cpid == 0) { /* Child reads from pipe */

close(pipefd[1]); /* Close unused write end */

 

while (read(pipefd[0], &buf, 1) > 0)

write(STDOUT_FILENO, &buf, 1);

 

write(STDOUT_FILENO, "\n", 1);

close(pipefd[0]);

_exit(EXIT_SUCCESS);

 

} else { /* Parent writes argv[1] to pipe */

close(pipefd[0]); /* Close unused read end */

write(pipefd[1], argv[1], strlen(argv[1]));

close(pipefd[1]); /* Reader will see EOF */

wait(NULL); /* Wait for child */

exit(EXIT_SUCCESS);

}

}

SEE ALSO

fork(2), read(2), socketpair(2), write(2), popen(3), pipe(7)

 

COLOPHON

This page is part of release 3.22 of the Linux man-pages project. A descrip-

tion of the project, and information about reporting bugs, can be found at

.

函数的原型:

int pipe(int pipefd[2]);

该函数的功能是创建无名管道。需要的头文件是unistd.h。返回值:

成功返回0,失败返回-1.

该函数有两个参数:

参数是一个数组,该数组有两个元素,一个读端,一个写端,返回值是两个文件描述符。

Pipefd[0]是读端的fd,pipefd[1]是写端的fd。

 

实例:创建一个管道用于父子进程间的通信:

pipe.c:

#include <unistd.h>

#include <stdio.h>

 

void main(){

 

    pid_t pid=0;

    int pipefd[2];

    char my_buf[12];

 

    //before fork() create a pipe

    pipe(pipefd);

 

    //create a child process

    pid = fork();

    if(pid>0){

        //father write something into pipe

        write(pipefd[1],"forfish",8);

        wait();//wait child process

        close(pipefd[1]);//close pipe

        exit(0);

    }

    if(pid == 0){

        //son

        read(pipefd[0],my_buf,8);

        printf("child read %s \n",my_buf);

        close(pipefd[0]);

        exit(0);

    }

}

 

运行结果:

我们看到上面的无名管道操作是基于父子进程的操作,因为管道一旦创建,就是两个文件,一个读端文件,一个写端文件。我们操作管道就是操作这两个文件。

 

转载于:https://www.cnblogs.com/FORFISH/p/5188655.html

你可能感兴趣的文章
学前班
查看>>
关于自关联1
查看>>
hdu-1814(2-sat)
查看>>
谷歌浏览器,添加默认搜索引擎的搜索地址
查看>>
数据结构化与保存
查看>>
为什么需要Docker?
查看>>
国内5家云服务厂商 HTTPS 安全性测试横向对比
查看>>
how to control project
查看>>
转 python新手容易犯的6个错误
查看>>
第四节 -- 列表
查看>>
决策树
查看>>
团队作业
查看>>
如何避免在简单业务逻辑上面的细节上面出错
查看>>
大型网站高并发的架构演变图-摘自网络
查看>>
8丶运行及总结
查看>>
Design Pattern --- Strategy
查看>>
mui列表跳转到详情页优化方案
查看>>
一些简单有用的方法合集
查看>>
Neutron 架构 - 每天5分钟玩转 OpenStack(67)
查看>>
详解JS设计模式
查看>>