六、进程间通信-有名管道

命名管道

  可用于没有亲缘关系的进程间进行数据传输,数据只能单向流动。

(1)创建管道

#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *filename,mode_t mode)
  • filename:用户读写的FIFO文件名。

  • mode:模式及权限参数说明:
    • O_RDONLY:只读管道。

    • O_WRONLY:只写管道

    • O_RDWR:读写管道。

    • O_NONBLOCK:非阻塞。

    • O_CREAT:如果该fifo文件不存在,那么就创建一个新的文件,并用第三个参数为其设置权限。

    • O_EXCL:如果使用O_CREAT时文件存在,那么可返回错误信息。这一参数可测试文件是否存在。

    函数返回值:
    • 0:成功

    • EACCESS:参数filename所指定的目录路径五可执行的权限。

    • EEXIST:参数filename所指定的文件已存在。 

    • ENAMETOOLONG:参数filename的路径名称太长。

    • ENOENT:参数filename包含的目录不存在。

    • ENOSPC:文件系统的剩余空间不足。

    • ENOTDIR:参数filename路径种的目录存在但却非真正的目录。

    • EROFS:参数filename指定的文件存在于只读文件系统内。

(2)特点 

  • 任意进程间数据传输

  • write和read操作可能会阻塞进程

  • write具有"原子性"

  • 使用FIFO的过程中,当一个进程对管道进行读操作时:
    • 若该管道是阻塞类型,且当前FIFO内没有数据,则对读进程而言将一直阻塞到有数据写入。

    • 若该管道是非阻塞类型,则不论FIFO内是否有数据,读进程都会立即执行读操作。即如果FIFO内没有数据,读函数将立即返回0.

  • 使用FIFO的过程中,当一个进程对管道进行写操作时:
    • 若该管道是阻塞类型,则写操作将一直阻塞到数据可以被写入。

    • 若该管道是非阻塞类型而不能写入全部数据,则写操作进行部分写入或者调用失败。

(3)使用步骤

 

  • 第一个进程mkfifo有名管道
  • open有名管道,write/read数据
  •  close有名管道
  • 第二个进程open有名管道,read/write数据
  • close有名管道

(4)实例

子进程写数据到FIFO文件,父进程读取文件数据

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>

#define MAX_BUFFER_SIZE PIPE_BUF  /*大小为4096,定义在limits.h种*/
#define MYFIFO "myfifo"

void fifo_read(void)
{
    char buff[MAX_BUFFER_SIZE];
    int fd;
    int nread;
    printf("********************read fifo***********************\n");
    if(access(MYFIFO,F_OK) == -1)
    {
        if((mkfifo(MYFIFO,0666) <0)&&(errno!=EEXIST))
        {
            printf("Cannot create FIFO file\n");
            exit(1);
        }
    }

    fd = open(MYFIFO,O_RDONLY);
    if(fd == -1)
    {
        printf("open fifo file error\n");
        exit(1);//exit(1)表示异常退出.这个1是返回给操作系统的,0表示正常退出。
    }
    memset(buff,0,MAX_BUFFER_SIZE);
    if((nread =  read(fd,buff,MAX_BUFFER_SIZE)) > 0)
    {
        printf("Read '%s' from FIFO\n",buff);
    }
    printf("********************close fifo******************************\n");
    close(fd);
    exit(0);

}

void fifo_write(void)
{
    int fd;
    char buff[] = "this is a fifo test demo";
    int nwrite;

    sleep(2);    //等待子进程先运行

    /*以只写阻塞方式打开FIFO管道*/
    fd = open(MYFIFO,O_WRONLY|O_CREAT,0644);
    if(fd == -1)
    {
        printf("Open fifo file error\n");
        exit(1);
    }

    printf("Write '%s' to FIFO\n",buff);

    /*向管道中写入字符串*/
    nwrite = write(fd,buff,MAX_BUFFER_SIZE);

    if(wait(NULL))//等待子进程退出
    {
        close(fd);
        exit(0);
    }

}

int main()
{
    pid_t result;
    result  = fork();

    if(result == -1)
    {
        printf("Fork error\n");
    }
    else if(result == 0) //子进程
    {
        fifo_read();

    }
    else    //父进程
    {
        fifo_write();
    }
    return result;
}

执行结果:

posted @ 2022-04-27 09:09  轻轻的吻  阅读(93)  评论(0编辑  收藏  举报