C语言 管道

  • Post author:
  • Post category:其他




管道

==================================================================


pipe (建立管道)


头文件:

 #include <unistd.h>


定义函数:

int pipe(int filedes[2]);


函数说明 :

  • pipe()会建立管道, 并将文件描述词由参数 filedes 数组返回. filedes[0]为管道里的读取端,

    filedes[1]则为管道的写入端.


返回值:

  • 若成功则返回零, 否则返回-1, 错误原因存于 errno 中.

    错误代码 EMFILE 进程已用完文件描述词最大量.

    ENFILE 系统已无文件描述词可用.

    EFAULT 参数 filedes 数组地址不合法.


DEMO:

#include <stdio.h> 
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

//函数声明
void func(void);

int main(int argc, char const *argv[])
{

    //创建一个无名管道 filedes[0]读取端 filedes[1]写入端
    int filedes[2];
    int ret = pipe(filedes);
    if(-1 == ret)
    {
        perror("pipe error\n");
        return -1;
    }

    //创建一个子进程
    pid_t x = fork();
    
    //子进程
    if(x == 0)
    {
        printf("[%d]this is child process\n", (int)getpid());
        
        //往无名管道写入端写
        char *buf = malloc(25);
        printf("child:");
        //从键盘输入
        bzero(buf, 25);
        fgets(buf, 25, stdin);
        write(filedes[1], buf, strlen(buf));
        
    }

    //父进程
    if(x > 0)
    {
        printf("[%d]this is father process\n", (int)getpid());
        
        //等待子进程退出
        wait(NULL);

        //从无名管道读取端读
        char *buf = malloc(25);
        bzero(buf, 25);
        read(filedes[0], buf, 25);
        printf("[%d]从无名管道子进程中读到的内容:%s",
                        (int)getpid(), buf);
        
    }

    ret = atexit(func);
    if(-1 == ret)
    {
        perror("atexit error\n");
    }
    

    #ifdef _EXIT
        _exit(0); //直接退出
    #else
        exit(0);  //正常退出
    #endif

}

void func(void)
{
    printf("[%d]eixt succeed\n", (int)getpid());
}

==================================================================


mkfifo ( 建立具名管道 )


头文件:


#include <sys/types.h>

#include <sys/stat.h>


定义函数 :

int mkfifo(const char * pathname, mode_t mode);


函数说明 :

  • mkfifo()会依参数 pathname 建立特殊的 FIFO 文件, 该文件必须不存在, 而参数 mode 为该文件的权限 (mode%~umask), 因此 umask 值也会影响到 FIFO 文件的权限. Mkfifo()建立的 FIFO 文件其他进程都可以用读写一般文件的方式存取. 当使用 open()来打开 FIFO 文件时, O_NONBLOCK 旗标会有影响
  1. 当使用 O_NONBLOCK 旗标时, 打开 FIFO 文件来读取的操作会立刻返回, 但是若还没有其他进

    程打开 FIFO 文件来读取, 则写入的操作会返回 ENXIO 错误代码.
  2. 没有使用 O_NONBLOCK 旗标时, 打开 FIFO 来读取的操作会等到其他进程打开 FIFO 文件来写入才正常返回. 同样地, 打开 FIFO 文件来写入的操作会等到其他进程打开 FIFO 文件来读取后才正常返回.


返回值 :

  • 若成功则返回 0, 否则返回-1, 错误原因存于 errno 中.

    错误代码 EACCESS 参数 pathname 所指定的目录路径无可执行的权限

    EEXIST 参数 pathname 所指定的文件已存在.

    ENAMETOOLONG 参数 pathname 的路径名称太长.

    ENOENT 参数 pathname 包含的目录不存在

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

    ENOTDIR 参数 pathname 路径中的目录存在但却非真正的目录.

    EROFS 参数 pathname 指定的文件存在于只读文件系统内.

==================================================================


access ( 判断是否具有存取文件的权限 )


头文件 :


#include <unistd.h>


定义函数 :

int access(const char * pathname, int mode);


函数说明 :

  • access()会检查是否可以读/写某一已存在的文件. 参数 mode 有几种情况组合, R_OK, W_OK, X_OK和 F_OK. R_OK, W_OK 与 X_OK 用来检查文件是否具有读娶写入和执行的权限. F_OK 则是用来判断该文件是否存在. 由于 access()只作权限的核查, 并不理会文件形态或文件内容, 因此, 如果一目录表示为”可写入”, 表示可以在该目录中建立新文件等操作, 而非意味此目录可以被当做文件处理. 例如, 你会发现 DOS 的文件都具有”可执行”权限, 但用 execve()执行时则会失败.


返回值:

  • 若所有欲查核的权限都通过了检查则返回 0 值, 表示成功, 只要有一权限被禁止则返回-1.

以下两个demo都得运行


DEMO1:

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

#define FIFO_PATH "/tmp/xxno/mkfifo" 
#define BUF_SIZE 30

int main(int argc, char const *argv[])
{
    //创建有名管道文件:
    if(access(FIFO_PATH, F_OK | W_OK))
    {
        int ret = mkfifo(FIFO_PATH, 0666);
        if(-1 == ret)
        {
            perror("mkfifo error\n");
            return -1;
        }
    }

    //打开管道文件:
    int fd_fifo = open(FIFO_PATH, O_WRONLY);
    if(-1 == fd_fifo)
    {
        perror("open error\n");
        return -1;
    }

    while(1)
    {
        //往管道文件里写内容:
        char *buf = malloc(BUF_SIZE);
        printf("写入管道中:\n");
        fgets(buf, BUF_SIZE, stdin);
        write(fd_fifo, buf, strlen(buf));
    }
    
    //关闭管道文件:
    close(fd_fifo);

    return 0 ;
}


DEMO2:

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

#define FIFO_PATH "/tmp/xxno/mkfifo" 
#define BUF_SIZE 30

int main(int argc, char const *argv[])
{
    //创建有名管道文件:
    if(access(FIFO_PATH, F_OK | R_OK))
    {
        int ret = mkfifo(FIFO_PATH, 0666);
        if(-1 == ret)
        {
            perror("mkfifo error\n");
            return -1;
        }
    }

    //打开管道文件:
    int fd_fifo = open(FIFO_PATH, O_RDONLY);
    if(-1 == fd_fifo)
    {
        perror("open error\n");
        return -1;
    }

    //往管道文件里写内容:
    while(1)
    {
        char *buf = malloc(BUF_SIZE);
        int ret = read(fd_fifo, buf, BUF_SIZE);
        if(0 == ret)
        {
            break;
        }
        printf("%s\n", buf);
    }
    
    //关闭管道文件:
    close(fd_fifo);

    return 0 ;
}



版权声明:本文为weixin_42191545原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。