mkfifo

创建一个有名管道

头文件:
    #include <sys/types.h>
    #include <sys/stat.h>
原型:
    int mkfifo(const char *pathname, mode_t mode);
参数:
    char *pathname:指定要创建的fifo文件路径及文件名;
    mode_t mode:有名管道的权限,(mode & ~umask);
返回值:
    成功,返回0;
    失败,返回-1,更新errno;如果有名管道已经存在,设置errno == EEXIST; 
例程:
     if(mkfifo("./myfifo", 0664) < 0)
    {
        if(errno != EEXIST)
        {
            perror("mkfifo");
            return -1;
        }
    }
    printf("创建成功\n");

open

打开有名管道

头文件:
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
原型:
    int open(const char *pathname, int flags);
参数:
    char *pathname:指定要打开的fifo文件路径及文件名;
    int flags:指定打开文件的方式:
        O_RDONLY     只读;阻塞,直到另外一个进程以写的方式打开同一个FIFO文件;
        O_WRONLY    只写;阻塞,直到另外一个进程以读的方式打开同一个FIFO文件;
        O_RDWR        读写;立即返回,不会阻塞;
        ------以上三种必须包含一种------
        --前两项可(或)上非阻塞方式打开--
        O_NONBLOCK    非阻塞方式打开
            O_RDONLY|O_NONBLOCK
            O_WRONLY|O_NONBLOCK
返回值:
    成功,返回文件描述符;
    失败,返回-1,更新errno;
例程:
    int fd = open("./myfifo", O_WRONLY);
    if(fd < 0)
    {
        perror("open");
        return -1;
    }
    printf("写端打开成功\n");

    int fd1 = open("./myfifo1", O_RDONLY);
    if(fd1<0)
    {
        perror("open");
        return -1;
    }
    printf("读端打开成功\n");

往有名管道 write 写数据

char buf[N] = "";
int res = write(fd, buf, strlen(buf));
if(res < 0)
{
    perror("write");
    return -1;
}

从有名管道 read 读数据

char buf[N] = "";
int res = read(fd1, buf, N);
if(res < 0)
{
    perror("read");
    return -1;
}
else if(0 == res)
{
    printf("对方关闭连接\n");
    break;
}

关闭管道

close(fd);

应用例程1

使用有名管道实现AB进程对话

  1. A进程发送一句话,B进程接收打印;
  2. B进程发送一句话,A进程接收打印。
  3. 重复1)2)两步骤
  4. 当A进程或B进程收到quit QUIT Quit,结束AB进程。

A进程

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#define N 128
int main(int argc, const char *argv[])
{
    if(mkfifo("./myfifo", 0664) < 0)
    {
        if(errno != EEXIST)
        {
            perror("mkfifo");
            return -1;
        }
    }
    printf("创建成功\n");
    if(mkfifo("./myfifo1", 0664) < 0)
    {
        if(errno != EEXIST)
        {
            perror("mkfifo");
            return -1;
        }
    }
    printf("创建成功\n");
    int fd = open("./myfifo", O_WRONLY);
    if(fd < 0)
    {
        perror("open");
        return -1;
    }
    printf("写端打开成功\n");
    int fd1 = open("./myfifo1", O_RDONLY);
    if(fd1<0)
    {
        perror("open");
        return -1;
    }
    printf("读端打开成功\n");
    char buf[N] = "";
    while(1)
    {
        bzero(buf, N);
        fprintf(stdout, "请输入>>>");
        fgets(buf, N, stdin);
        buf[strlen(buf)-1] = 0;
        int res = write(fd, buf, N);
        if(res < 0)
        {
            perror("write");
            return -1;
        }
        //从B中读取数据
        bzero(buf, N);
        res = read(fd1, buf, N);
        if(res < 0)
        {
            perror("read");
            return -1;
        }
        else if(0 == res)
        {
            printf("对方关闭\n");
            break;
        }
        printf("B说:%s\n", buf);
    }
    close(fd);
    return 0;
}

B进程

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#define N 128
int main(int argc, const char *argv[])
{
    if(mkfifo("./myfifo", 0664) < 0)
    {
        if(errno != EEXIST)
        {
            perror("mkfifo");
            return -1;
        }
    }
    printf("创建成功\n");
    if(mkfifo("./myfifo1", 0664) < 0)
    {
        if(errno != EEXIST)
        {
            perror("mkfifo");
            return -1;
        }
    }
    printf("创建成功\n");
    int fd = open("./myfifo", O_RDONLY);
    if(fd < 0)
    {
        perror("open");
        return -1;
    }
    printf("读端打开成功\n");
    int fd1 = open("./myfifo1", O_WRONLY);
    if(fd1 < 0)
    {
        perror("open");
        return -1;
    }
    printf("写端打开成功\n");
    char buf[N] = "";
    while(1)
    {
        bzero(buf, N);
        int res = read(fd, buf, N);
        if(res < 0)
        {
            perror("read");
            return -1;
        }
        else if(0 == res)
        {
            printf("对方关闭\n");
            break;
        }
        printf("A说:%s\n", buf);
        //往A发送数据
        bzero(buf, N);
        fprintf(stdout, "请输入>>>");
        fgets(buf, N, stdin);
        buf[strlen(buf)-1] = 0;
        res = write(fd1, buf, N);
        if(res < 0)                                     
        {
            perror("write");
            return -1;
        }
    }
    close(fd);
    return 0;
}

应用例程2

在应用例程1的基础上,实现AB进程可以随时发送,随时接收

A进程

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <stdlib.h>
#define N 128
void* aTob(void*arg)
{
    int fd = *(int*)arg;
    char buf[N];
    while(1)
    {
        bzero(buf, N);
        fgets(buf, N, stdin);
        buf[strlen(buf)-1] = 0;
        if(write(fd, buf, N)<0)
        {
            perror("write");
            pthread_exit(NULL);
        }
    }
    pthread_exit(NULL);
}
//读取B的信息
void* bToa(void*arg)
{
    int fd = *(int*)arg;
    char buf[N];
    while(1)
    {
        bzero(buf, N);
        int res = read(fd, buf, N);
        if(res < 0)
        {
            perror("read");
            pthread_exit(NULL);
        }
        else if(0 == res)
        {
            printf("对方关闭\n");
            exit(1);
        }
        printf("B说:%s\n", buf);
    }
    pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
    //创建两个有名管道
    //myfifo: A-->B
    if(mkfifo("./myfifo", 0664))
    {
        if(errno != EEXIST)
        {
            perror("errno");
            return -1;
        }
    }
    //myfifo1 B-->A
    if(mkfifo("./myfifo1", 0664))
    {
        if(errno != EEXIST)
        {
            perror("errno");
            return -1;
        }
    }
    //打开有名管道
    int fd_w = open("./myfifo", O_WRONLY);
    if(fd_w<0)
    {
        perror("open");
        return -1;
    }
    int fd_r = open("./myfifo1", O_RDONLY);
    if(fd_r < 0)
    {
        perror("open");
        return -1;
    }
    //创建两个线程 一个读线程,一个写线程
    pthread_t tid_w, tid_r;
    if(pthread_create(&tid_w, NULL, aTob, (void*)&fd_w)!=0)
    {
        perror("pthread_create");
        return -1;
    }
    if(pthread_create(&tid_r, NULL, bToa, (void*)&fd_r)!=0)
    {
        perror("pthread_create");
        return -1;
    }
    pthread_join(tid_w, NULL);
    pthread_join(tid_r, NULL);
    close(fd_w);
    close(fd_r);
    return 0;
}

B进程

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <stdlib.h>
#define N 128
void* bToa(void*arg)
{
    int fd = *(int*)arg;
    char buf[N];
    while(1)
    {
        bzero(buf, N);
        fgets(buf, N, stdin);
        buf[strlen(buf)-1] = 0;
        if(write(fd, buf, N)<0)
        {
            perror("write");
            pthread_exit(NULL);
        }
    }
    pthread_exit(NULL);
}
//读取A的信息
void* aTob(void*arg)
{
    int fd = *(int*)arg;
    char buf[N];
    while(1)
    {
        bzero(buf, N);
        int res = read(fd, buf, N);
        if(res < 0)
        {
            perror("read");
            pthread_exit(NULL);
        }
        else if(0 == res)
        {
            printf("对方关闭\n");
            exit(1);
        }
        printf("A说:%s\n", buf);
    }
    pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
    //创建两个有名管道
    //myfifo: A-->B
    if(mkfifo("./myfifo", 0664))
    {
        if(errno != EEXIST)
        {
            perror("errno");
            return -1;
        }
    }
    //myfifo1 B-->A
    if(mkfifo("./myfifo1", 0664))
    {
        if(errno != EEXIST)
        {
            perror("errno");
            return -1;
        }
    }
    //打开有名管道
    int fd_r = open("./myfifo", O_RDONLY);
    if(fd_r < 0)
    {
        perror("open");
        return -1;
    }
    int fd_w = open("./myfifo1", O_WRONLY);
    if(fd_w<0)
    {
        perror("open");
        return -1;
    }
    //创建两个线程 一个读线程,一个写线程
    pthread_t tid_w, tid_r;
    if(pthread_create(&tid_w, NULL, bToa, (void*)&fd_w)!=0)
    {
        perror("pthread_create");
        return -1;
    }
    if(pthread_create(&tid_r, NULL, aTob, (void*)&fd_r)!=0)
    {
        perror("pthread_create");
        return -1;
    }
    pthread_join(tid_w, NULL);
    pthread_join(tid_r, NULL);
    close(fd_w);
    close(fd_r);
    return 0;
}

结果

Last modification:2021 年 04 月 08 日 02 : 50 : 13