Linux IPC(一):管道

前言

Linux进程间通信(IPC)的一个重要方法就是管道,在学习管道之前,要理解两个概念

  • 半双工(读端与写端必须固定)
  • 全双工(读端与写端不固定)

不论是无名管道还是有名管道,都属于半双工管道,理解这一点非常重要。

一.标准管道流

  • FILE *popen(const char *__command, const char *__modes)
    command 代表shell指令
    modes 分为 "r"读 和 "w"写
    具体功能和Linux命令中的管道基本相同
void test1()
{
    //读
    FILE *fp = popen("cat /etc/profile", "r");
    char buf[1000] = {0};
    while (fread(buf, sizeof(char), sizeof(buf), fp))
        cout << buf;
    cout << endl;
    pclose(fp);

    //写
    char buf2[] = {"aaa bbb ccc ddd eee fff ggg hhh"};
    FILE *fp2 = popen("wc -w", "w");
    fwrite(buf2, sizeof(char), sizeof(buf2), fp2);
    pclose(fp2);
}

二.无名管道

  • 只能在亲缘进程之间使用
  • 为半双工管道(即只能一端读,一端写)
  • 无名管道是特殊的文件,只能存在于内存中

注意:无名管道中的 read 函数会进行阻塞。

案例:创建一个无名管道 与 父子进程,进行父写子读

void test2()
{
    int fds[2] = {0};
    pipe(fds);//fds[0] = 3, fds[1] = 4;
    if (fork() == 0)
    {
        close(fds[1]);
        char buf[100] = {0};
        read(fds[0], buf, sizeof(buf));
        cout << "child process reading:" << buf << endl;
        close(fds[0]);
        exit(0);
    }
    close(fds[0]);
    char buf[100] = "Helloworld";
    write(fds[1], buf, strlen(buf));
    cout << "father process is writing" << endl;
    close(fds[1]);
    wait(NULL);
}

三.命名管道

命名管道比起无名管道,即便不是亲属进程也能够进行进程间通信
另外,命名管道可以作为文件存在。
需要使用 mkfifo 命令创建命名管道

命名管道:读写操作案例

分别创建好 读端写端 , 并设置退出机制

注意:如果没有设置退出机制,那么read端 将会默认一直在接收 0 个字符,读端将会一直打印空字符串

写端 (write.cpp)

int main()
{
    int fdw = open("pipe", O_WRONLY);
    ERROR_CHECK(fdw, -1 ,"open w");
    char buf[100] = {0};
    while (1)
    {
        memset(buf, 0, sizeof(buf));
        read(0, buf, sizeof(buf));
        write(fdw, buf, strlen(buf) - 1);
    }
    return 0;
}

读端(read.cpp):

int main()
{
    int fdr = open("pipe", O_RDONLY);
    ERROR_CHECK(fdr, -1, "open r");
    char buf[100] = {0};
    int ret;
    while (1)
    {
        memset(buf, 0, sizeof(buf));
        ret = read(fdr, buf, sizeof(buf));
        if (ret == 0)
        {
            cout << "byebye" << endl;
            break;
        }
        cout << "ret = " << ret << endl;
        cout << "buf = " << buf << endl;
    }
    return 0;
}

通过以上程序,可以实现一端写,一段读的案例。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章