0

0

linux编程之pipe()函数

高洛峰

高洛峰

发布时间:2016-12-13 11:31:01

|

1766人浏览过

|

来源于php中文网

原创

管道是一种把两个进程之间的标准输入和标准输出连接起来的机制,从而提供一种让多个进程间通信的方法,当进程创建管道时,每次

都需要提供两个文件描述符来操作管道。其中一个对管道进行写操作,另一个对管道进行读操作。对管道的读写与一般的IO系统函数一

致,使用write()函数写入数据,使用read()读出数据。

linux编程之pipe()函数

#include

int pipe(int filedes[2]);

返回值:成功,返回0,否则返回-1。参数数组包含pipe使用的两个文件的描述符。fd[0]:读管道,fd[1]:写管道。

必须在fork()中调用pipe(),否则子进程不会继承文件描述符。两个进程不共享祖先进程,就不能使用pipe。但是可以使用命名管道。

linux编程之pipe()函数

linux编程之pipe()函数

linux编程之pipe()函数

当管道进行写入操作的时候,如果写入的数据小于128K则是非原子的,如果大于128K字节,缓冲区的数据将被连续地写入

管道,直到全部数据写完为止,如果没有进程读取数据,则将一直阻塞,如下:

linux编程之pipe()函数

linux编程之pipe()函数

linux编程之pipe()函数

ecshop
ecshop

本版本全面兼容php5.6+,并且修复了许多官方程序的低级代码bug。在apache 2.4.17+php5.6.15环境下测试通过,人格保证无毒无木马,仅仅是一名ecshop热爱者心血来潮之作。ecshop编译更新日志:1、加入最新官方补丁。2、修改数据库连接底层为mysqli, 现在完美无缺了。3、再次对所有代码进行细节修复。4、adminers更新至1.1.2, 在线管理数据库的神器。5、测

下载

linux编程之pipe()函数

在上例程序中,子进程一次性写入128K数据,当父进程将全部数据读取完毕的时候,子进程的write()函数才结束阻塞并且

返回写入信息。

命名管道FIFO

管道最大的劣势就是没有名字,只能用于有一个共同祖先进程的各个进程之间。FIFO代表先进先出,单它是一个单向数据流,也就是半双工,和

管道不同的是:每个FIFO都有一个路径与之关联,从而允许无亲缘关系的进程访问。  

        #include

        #include

      int mkfifo(const char *pathname, mode_t mode);
     这里pathname是路径名,mode是sys/stat.h里面定义的创建文件的权限.

以下示例程序来自:http://blog.chinaunix.net/uid-20498361-id-1940238.html

  有亲缘关系进程间的fifo的例子

/*
 * 有亲缘关系的进程间的fifo的使用
 * fifo 使用的简单例子
 */

#include "../all.h"

#define FIFO_PATH "/tmp/hover_fifo"


void 
do_sig(int signo)
{
    if (signo == SIGCHLD)
        while (waitpid(-1, NULL, WNOHANG) > 0)
            ;
}

int
main(void)
{
    int ret;
    int fdr, fdw;
    pid_t pid;

    char words[10] = "123456789";
    char buf[10] = {'\0'};    
    
    // 创建它,若存在则不算是错误,
    // 若想修改其属性需要先打开得到fd,然后用fcntl来获取属性,然后设置属性.

    if (((ret = mkfifo(FIFO_PATH, FILE_MODE)) == -1) 
                     && (errno != EEXIST))
        perr_exit("mkfifo()");
    fprintf(stderr, "fifo : %s created successfully!\n", FIFO_PATH);

    signal(SIGCHLD, do_sig);

    pid = fork();
    if (pid == 0) { // child

        if ((fdr = open(FIFO_PATH, O_WRONLY)) < 0) // 打开fifo用来写
            perr_exit("open()");
        sleep(2);
        // 写入数据
        if (write(fdr, words, sizeof(words)) != sizeof(words)) 
            perr_exit("write");
        fprintf(stderr, "child write : %s\n", words);
        close(fdw);
    } else if (pid > 0) { // parent

        if ((fdr = open(FIFO_PATH, O_RDONLY)) < 0) // 打开fifo用来读

            perr_exit("open()");

        fprintf(stderr, "I father read, waiting for child ...\n");
        if (read(fdr, buf, 9) != 9) //读数据
            perr_exit("read");

        fprintf(stderr, "father get buf : %s\n", buf);
        close(fdr);
    }
    // 到这里fifo管道并没有被删除,必须手动调用函数unlink或remove删除.

    return 0;    
}

从例子上可以看出使用fifo时需要注意:
*fifo管道是先调用mkfifo创建,然后再用open打开得到fd来使用.
*在打开fifo时要注意,它是半双工的的,一般不能使用O_RDWR打开,而只能用只读或只写打开.

   fifo可以用在非亲缘关系的进程间,而它的真正用途是在服务器和客户端之间. 由于它是半双工的所以,如果要进行客户端和服务器双方的通信的话,

每个方向都必须建立两个管道,一个用于读,一个用于写.

下面是一个服务器,对多个客户端的fifo的例子:

server 端的例子:

/*
 * FIFO server
 */

#include "all.h"

int
main(void)
{
    int fdw, fdw2;
    int fdr;
    char clt_path[PATH_LEN] = {'\0'};
    char buf[MAX_LINE] = {'\0'};
    char *p;
    int n;
    
    if (mkfifo(FIFO_SVR, FILE_MODE) == -1 && errno != EEXIST)    
        perr_exit("mkfifo()");    
    if ((fdr = open(FIFO_SVR, O_RDONLY)) < 0)    
        perr_exit("open()");
    /* 
     * 根据fifo的创建规则, 若从一个空管道或fifo读, 
     * 而在读之前管道或fifo有打开来写的操作, 那么读操作将会阻塞 
     * 直到管道或fifo不打开来读, 或管道或fifo中有数据为止. 
     *
     * 这里,我们的fifo本来是打开用来读的,但是为了,read不返回0,
     * 让每次client端读完都阻塞在fifo上,我们又打开一次来读.
     * 见unpv2 charper 4.7
     */
    if ((fdw2 = open(FIFO_SVR, O_WRONLY)) < 0)    
        fprintf(stderr, "open()");
    
    while (1) {
        /* read client fifo path from FIFO_SVR */
     /* 这里由于FIFO_SVR有打开来写的操作,所以当管道没有数据时, 
      * read会阻塞,而不是返回0. 
      */
        if (read(fdr, clt_path, PATH_LEN) < 0) {
            fprintf(stderr, "read fifo client path error : %s\n", strerror(errno));    
            break;
        }
        if ((p = strstr(clt_path, "\r\n")) == NULL) {
            fprintf(stderr, "clt_path error: %s\n", clt_path);
            break;
        }
        *p = '\0';
        DBG("clt_path", clt_path);
        if (access(clt_path, W_OK) == -1) { // client fifo ok, but no permission

            perror("access()");    
            continue;
        }
        /* open client fifo for write */
        if ((fdw = open(clt_path, O_WRONLY)) < 0) {
            perror("open()");    
            continue;
        }
        if ((n = read(fdr, buf, WORDS_LEN)) > 0) { /* read server words is ok */
            printf("server read words : %s\n", buf);
            buf[n] = '\0';
            write(fdw, buf, strlen(buf));    
        }
    }
    
    close(fdw);    
    unlink(FIFO_SVR);
    exit(0);
}

客户端的例子:

/*
 * Fifo client
 *
 */
#include "all.h"



int
main(void)
{
    int fdr, fdw;
    pid_t pid;    
    char clt_path[PATH_LEN] = {'\0'};
    char buf[MAX_LINE] = {'\0'};
    char buf_path[MAX_LINE] = {'\0'};
    
    snprintf(clt_path, PATH_LEN, FIFO_CLT_FMT, (long)getpid());        
    DBG("clt_path1 = ", clt_path);
    snprintf(buf_path, PATH_LEN, "%s\r\n", clt_path);

    if (mkfifo(clt_path, FILE_MODE) == -1 && errno != EEXIST)    
        perr_exit("mkfifo()");

    /* client open clt_path for read
     * open server for write 
       */
    if ((fdw = open(FIFO_SVR, O_WRONLY)) < 0) 
        perr_exit("open()");
    
    /* write my fifo path to server */    
    if (write(fdw, buf_path, PATH_LEN) != PATH_LEN)        
        perr_exit("write()");
    if (write(fdw, WORDS, WORDS_LEN) < 0)    /* write words to fifo server */
        perr_exit("error");

    if ((fdr = open(clt_path, O_RDONLY)) < 0)    
        perr_exit("open()");
    if (read(fdr, buf, WORDS_LEN) > 0) {     /* read reply from fifo server */
        buf[WORDS_LEN] = '\0';
        printf("server said : %s\n", buf);
    }
    
    close(fdr);
    unlink(clt_path);
    
    exit(0);
}

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
go语言 注释编码
go语言 注释编码

本专题整合了go语言注释、注释规范等等内容,阅读专题下面的文章了解更多详细内容。

32

2026.01.31

go语言 math包
go语言 math包

本专题整合了go语言math包相关内容,阅读专题下面的文章了解更多详细内容。

23

2026.01.31

go语言输入函数
go语言输入函数

本专题整合了go语言输入相关教程内容,阅读专题下面的文章了解更多详细内容。

16

2026.01.31

golang 循环遍历
golang 循环遍历

本专题整合了golang循环遍历相关教程,阅读专题下面的文章了解更多详细内容。

5

2026.01.31

Golang人工智能合集
Golang人工智能合集

本专题整合了Golang人工智能相关内容,阅读专题下面的文章了解更多详细内容。

6

2026.01.31

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

268

2026.01.31

高干文在线阅读网站大全
高干文在线阅读网站大全

汇集热门1v1高干文免费阅读资源,涵盖都市言情、京味大院、军旅高干等经典题材,情节紧凑、人物鲜明。阅读专题下面的文章了解更多详细内容。

195

2026.01.31

无需付费的漫画app大全
无需付费的漫画app大全

想找真正免费又无套路的漫画App?本合集精选多款永久免费、资源丰富、无广告干扰的优质漫画应用,涵盖国漫、日漫、韩漫及经典老番,满足各类阅读需求。阅读专题下面的文章了解更多详细内容。

170

2026.01.31

漫画免费在线观看地址大全
漫画免费在线观看地址大全

想找免费又资源丰富的漫画网站?本合集精选2025-2026年热门平台,涵盖国漫、日漫、韩漫等多类型作品,支持高清流畅阅读与离线缓存。阅读专题下面的文章了解更多详细内容。

85

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 8.3万人学习

Git 教程
Git 教程

共21课时 | 3.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号