`

linux c学习笔记----管道文件(pipe,popen,mkfifo,pclose,dup2)

阅读更多

 

pipe(建立管道) 


相关函数
mkfifo,popen,read,write,fork
表头文件
#include<unistd.h>
定义函数
int pipe(int filedes[2]);
函数说明
pipe()会建立管道,并将文件描述词由参数filedes数组返回。filedes[0]为管道里的读取端,filedes[1]则为管道的写入端。
返回值
若成功则返回零,否则返回-1,错误原因存于errno中。
错误代码
EMFILE 进程已用完文件描述词最大量。
ENFILE 系统已无文件描述词可用。
EFAULT 参数filedes数组地址不合法。
范例
/* 父进程借管道将字符串“hello!\n”传给子进程并显示*/
#include <unistd.h>
main()
{
int filedes[2];
char buffer[80];
pipe(filedes);
if(fork()>0){
/* 父进程*/
char s[ ] = “hello!\n”;
write(filedes[1],s,sizeof(s));
}
else{
/*子进程*/
read(filedes[0],buffer,80);
printf(“%s”,buffer);
}
}
执行
hello!

 实例:

 

 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#define BUFFER 255

int main(int argc, char **argv) {
    char buffer[BUFFER + 1];
    int fd[2];
    if (argc != 2) {
        fprintf(stderr, "Usage:%s string\n\a", argv[0]);
        exit(1);
    }
    if (pipe(fd) != 0) {
        fprintf(stderr, "Pipe Error:%s\n\a", strerror(errno));
        exit(1);
    }
    if (fork() == 0) {
        close(fd[0]);
        printf("Child[%d] Write to pipe\n\a", getpid());
        snprintf(buffer, BUFFER, "%s", argv[1]);
        write(fd[1], buffer, strlen(buffer));
        printf("Child[%d] Quit\n\a", getpid());
        exit(0);
    } else {
        close(fd[1]);
        printf("Parent[%d] Read from pipe\n\a", getpid());
        memset(buffer, '\0', BUFFER + 1);
        read(fd[0], buffer, BUFFER);
        printf("Parent[%d] Read:%s\n", getpid(), buffer);
        exit(1);
    }
}

 

popen(建立管道I/O)

 




相关函数
pipe,mkfifo,pclose,fork,system,fopen
表头文件
#include<stdio.h>
定义函数
FILE * popen( const char * command,const char * type);
函数说明
popen()会调用fork()产生子进程,然后从子进程中调用/bin/sh -c来执行参数command的指令。参数type可使用“r”代表读取,“w”代表写入。依照此type值,popen()会建立管道连到子进程的标准输出设备或标准输入设备,然后返回一个文件指针。随后进程便可利用此文件指针来读取子进程的输出设备或是写入到子进程的标准输入设备中。此外,所有使用文件指针(FILE*)操作的函数也都可以使用,除了fclose()以外。
返回值
若成功则返回文件指针,否则返回NULL,错误原因存于errno中。
错误代码
EINVAL参数type不合法。
注意事项
在编写具SUID/SGID权限的程序时请尽量避免使用popen(),popen()会继承环境变量,通过环境变量可能会造成系统安全的问题。
范例
#include<stdio.h>
main()
{
FILE * fp;
char buffer[80];
fp=popen(“cat /etc/passwd”,”r”);
fgets(buffer,sizeof(buffer),fp);
printf(“%s”,buffer);
pclose(fp);
}
执行
root :x:0 0: root: /root: /bin/bash

 

 

mkfifo(建立具名管道)

 


相关函数
pipe,popen,open,umask
表头文件
#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指定的文件存在于只读文件系统内。
范例
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
char *FIFO = "/tmp/my_fifo";
main()
{
char buffer[80];
int fd;
unlink(FIFO);
mkfifo(FIFO,0666);
if(fork()>0){
char s[ ] = “hello!\n”;
fd = open (FIFO,O_WRONLY);
write(fd,s,sizeof(s));
close(fd);
}
else{
fd= open(FIFO,O_RDONLY);
read(fd,buffer,80);
printf(“%s”,buffer);
close(fd);
}
}
 
执行
hello!

 

 

 

pclose(关闭管道I/O)

相关函数
popen
表头文件
#include<stdio.h>
定义函数
int pclose(FILE * stream);
函数说明
pclose()用来关闭由popen所建立的管道及文件指针。参数stream为先前由popen()所返回的文件指针。
返回值
返回子进程的结束状态。如果有错误则返回-1,错误原因存于errno中。
错误代码
ECHILD pclose()无法取得子进程的结束状态。
范例
参考popen()。

 

 

为了实现重定向操作,我们需要调用另外一个函数dup2

 

dup2(复制文件描述词)

 


相关函数
open,close,fcntl,dup
表头文件
#include<unistd.h>
定义函数
int dup2(int odlfd,int newfd);
函数说明
dup2()用来复制参数oldfd所指的文件描述词,并将它拷贝至参数newfd后一块返回。若参数newfd为一已打开的文件描述词,则newfd所指的文件会先被关闭。dup2()所复制的文件描述词,与原来的文件描述词共享各种文件状态,详情可参考dup()。
返回值
当复制成功时,则返回最小及尚未使用的文件描述词。若有错误则返回-1,errno会存放错误代码。
附加说明
dup2()相当于调用fcntl(oldfd,F_DUPFD,newfd);请参考fcntl()。
错误代码
EBADF 参数fd 非有效的文件描述词,或该文件已关闭

实例:

 

#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#define BUFFER_SIZE 1024

int main(int argc, char **argv) {
    int fd;
    char buffer[BUFFER_SIZE];
    if (argc != 2) {
        fprintf(stderr, "Usage:%s outfilename\n\a", argv[0]);
        exit(1);
    }
    if ((fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) == -1) {
        fprintf(stderr, "Open %s Error:%s\n\a", argv[1], strerror(errno));
        exit(1);
    }
    if (dup2(fd, STDOUT_FILENO) == -1) {
        fprintf(stderr, "Redirect Standard Out Error:%s\n\a", strerror(errno));
        exit(1);
    }
    fprintf(stderr, "Now,please input string");
    fprintf(stderr, "(To quit use CTRL+D)\n");
    while (1) {
        fgets(buffer, BUFFER_SIZE, stdin);
        if (feof(stdin))break;
        write(STDOUT_FILENO, buffer, strlen(buffer));
    }exit(0)}
分享到:
评论

相关推荐

    linux shell窗口工具-qt5源码

    linux shell命令窗口工具-qt5源码,一个简单的qt5程序,使用简单控件,使用pipe,popen().初学qt5可以参考

    Linux系统中popen函数的缺陷与改造方案.pdf

    Linux系统中popen函数的缺陷与改造方案.pdf

    linux popen函数

    linux popen函数linux popen函数linux popen函数linux popen函数

    mypopen_popen实现_经过测试_绝对可用_

    pclose是阻塞函数,一般情况下,如果使用popen执行一些命令时,如果需要读取一部分信息,此时直接调用pclose函数,会阻塞,如果想不阻塞,需要自己实现pclose函数,目前给出经过测试的自己实现的my_popen

    Linux下使用popen()执行shell命令.docx

    Linux下使用popen()执行shell命令.docx

    popen使用介绍(en)

    育龙网核心提示: use popen ====================================================================from: NAMEpopen - initiate pipe streams t use popen ==================================================...

    c语言 fork pipe 实现popen plcose

    参考popen, pclose源码进行了修改 第一次的问题已解决 如下图 #include #include #include #include #include #include #include #include #include #include #include #include #include #define SHELL /bin/bash...

    对Python subprocess.Popen子进程管道阻塞详解

    问题产生描述 ... p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) p.wait() # 从标准输出读出shell命令的输出结果 #rt = p.stdout.read().decode() #

    UNIX环境高级编程_第2版.part2

    15.3 popen和pclose函数403 15.4 协同进程408 15.5 fifo 412 15.6 xsi ipc 415 15.6.1 标识符和键415 15.6.2 权限结构416 15.6.3 结构限制417 15.6.4 优点和缺点417 15.7 消息队列418 15.8 信号量422 15.9...

    UNIX环境高级编程_第2版.part1

    15.3 popen和pclose函数403 15.4 协同进程408 15.5 fifo 412 15.6 xsi ipc 415 15.6.1 标识符和键415 15.6.2 权限结构416 15.6.3 结构限制417 15.6.4 优点和缺点417 15.7 消息队列418 15.8 信号量422 15.9...

    popen 实现c/s模式shell功能

    通过接受客户端从管道中写入的命令,执行,并将返回结果写入管道由客户端读出。 Server端通过socket套接字接收client 端发出的信息,发送到套接字中的内容包括数据的长度,以及数据的内容。 Server端需要先接收...

    重新实现popen和system函数

    重写系统提供的system和popen函数,在fork之后关闭所有的从3到最大的文件描述符

    linux中管道通信的例子,获取标准输出的内容

    这是一个演示linux下线程之间如何进行通讯的例子,使用了管道技术。主要使用了popen函数

    Linux中popen函数的作用小结

    popen()函数通过创建一个管道,调用fork()产生一个子进程,执行一个shell以运行命令来开启一个进程。这篇文章重点给大家介绍Linux中popen函数的作用,感兴趣的朋友一起看看吧

    tcps.zip_linux 远程控制_popen

    用pipe实现远程控制系统中的popen函数功能。参数f_des[0]从管道中读数据,f_des[1]向管道中写数据。通过管道实现父子进程间的通信。服务器可以向多个用户提供服务。

    popen 获取ip ,mask,dns等1.2 测试ok

    最近在做web服务器端处理。刚好用到要在服务器端调用popen函数查询相关命令,并上传到前端。所以在服务器端做的查询ip,mask等的测试代码。在linux下编译运行即可得到需要的值。代码简单。

    从Linux程序中执行shell(程序、脚本)并获得输出结果

    2. 使用临时文件 3. 使用匿名管道 4. 使用popen 5. 小结 1. 前言 Unix界有一句名言:“一行shell脚本胜过万行C程序”,虽然这句话有些夸张,但不可否认的是,借助脚本确实能够极大的简化一些编程工作。比如实现...

    自己写的popen

    自己编写popen函数,可以学习学习哦,网上有popen的源代码

    linux下几种最常用的IPC接口,这样一来,统一了接口,提高代码重用性.rar

    Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间。...2、管道(Pipe) 管道用来连接不同进程之间的数据流。 (1)在两个程序之间传递数据的最简单的方法是使用popen()和pclose()函数:

Global site tag (gtag.js) - Google Analytics