popen 函数

函数原型:

#include<stdio.h>

FILE*   popen(const  char*  command,    const   char*  type);

void  pclose(FILE*  stream);

man文本英语描述:

DESCRIPTION:
       The popen() function opens a process by creating a pipe,  forking,  and
       invoking  the shell.  Since a pipe is by definition unidirectional, the
       type argument may specify  only  reading  or  writing,  not  both;  the
       resulting stream is correspondingly read-only or write-only.

The  command argument is a pointer to a null-terminated string contain‐
       ing a shell command line.  This command is passed to /bin/sh using  the
       -c  flag;  interpretation, if any, is performed by the shell.  The type
       argument is a pointer to a null-terminated string  which  must  contain
       either the letter ‘r‘ for reading or the letter ‘w‘ for writing.  Since
       glibc 2.9, this argument can additionally include the letter ‘e‘, which
       causes  the close-on-exec flag (FD_CLOEXEC) to be set on the underlying
       file descriptor; see the description of the O_CLOEXEC flag  in  open(2)
       for reasons why this may be useful.

RETURN VALUE:
       The popen() function returns NULL if the fork(2) or pipe(2) calls fail,
       or if it cannot allocate memory.
       The pclose() function returns -1 if wait4(2) returns an error, or  some
       other error is detected.  In the event of an error, these functions set
       errno to indicate the cause of the error.
ERRORS:
       The popen() function does not set errno if memory allocation fails.  If
       the  underlying  fork(2)  or pipe(2) fails, errno is set appropriately.
       If the type argument is invalid, and this condition is detected,  errno
       is set to EINVAL.
       If pclose() cannot obtain the child status, errno is set to ECHILD.

中文总结:

  1. popen函数是通过创建一个管道的方式打开一个进程,并调用shell。因为管道是被定义为单向的,所以type的值只能是r或w其中的一个,结果流也是如此。
  2. command(命令行/命令的意思)参数:是一个以NULL结尾的字符串,这个字符串应是一个shell命令。这个命令会被送到 /bin/sh中,并以 -c执行即被shell执行。
  3. type参数:只能是r或w中的一个,r或w是相当command管道而言的。r表示从command管道中读,w表示通过command管道输出到stdout中(输出流为全缓冲)。
  4. 返回值:如果fork或者pipe失败,或者不能分配到内存都会返回NULL,成功则返回标志I/O流。popen没有为申请内存失败设置errno值,但fork和pipe都有其相应的errno值。如果type参数不合法,errno会别设置为EINVAL.

注意:只能用pclose函数进行关闭操作,不能用fclose。

相关代码:

type为  r时:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<string.h>
const int BUF_SIZE = 1024;

int main()
{
    FILE* stream;
    FILE* wstream;
    char buf[BUF_SIZE];

stream = popen("ls -l","r");
    wstream = fopen("test_popen.txt","w+");

memset(buf, ‘\0‘, sizeof(buf));
    fread(buf, sizeof(char), sizeof(buf), stream);//把返回标准I/O流内的内容读到buf中
    fwrite(buf,sizeof(char), strlen(buf), wstream);

fclose(wstream);//一定要记得关闭
    pclose(stream);//只能用pclose不能用fclose

return 0;
}

执行结果:

当type为 w  时:(此时popen函数会通过FIFO管道直接向stdout中写数据)

#include<stdio.h>

int main()
{
    FILE* stream;
    stream = popen("ls -l","w");
    if(stream == NULL)
    {
        perror("popen");
        return -1;
    }
    pclose(stream);
    return 0;
}

注意:一个执行的命令是 cat  test_popen.txt        一个是./a.out

以下是在网上找到的popen函数和pclose函数实现的代码:

Figure 15.12. The popen and pclose functions

#include "apue.h"

#include <errno.h>

#include <fcntl.h>

#include <sys/wait.h>

/*

* Pointer to array allocated at run-time.

*/

static pid_t    *childpid = NULL;

/*

* From our open_max(), Figure 2.16.

*/

static int      maxfd;

FILE *

popen(const char *cmdstring, const char *type)

{

int     i;

int     pfd[2];

pid_t   pid;

FILE    *fp;

/* only allow "r" or "w" */

if ((type[0] != ‘r‘ && type[0] != ‘w‘) || type[1] != 0) {

errno = EINVAL;     /* required by POSIX */

return(NULL);

}

if (childpid == NULL) {     /* first time through */

/* allocate zeroed out array for child pids */

maxfd = open_max();

if ((childpid = calloc(maxfd, sizeof(pid_t))) == NULL)

return(NULL);

}

if (pipe(pfd) < 0)

return(NULL);   /* errno set by pipe() */

if ((pid = fork()) < 0) {

return(NULL);   /* errno set by fork() */

} else if (pid == 0) {                           /* child */

if (*type == ‘r‘) {

close(pfd[0]);

if (pfd[1] != STDOUT_FILENO) {

dup2(pfd[1], STDOUT_FILENO);

close(pfd[1]);

}

} else {

close(pfd[1]);

if (pfd[0] != STDIN_FILENO) {

dup2(pfd[0], STDIN_FILENO);

close(pfd[0]);

}

}

/* close all descriptors in childpid[] */

for (i = 0; i < maxfd; i++)

if (childpid[i] > 0)

close(i);

execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);

_exit(127);

}

/* parent continues... */

if (*type == ‘r‘) {

close(pfd[1]);

if ((fp = fdopen(pfd[0], type)) == NULL)

return(NULL);

} else {

close(pfd[0]);

if ((fp = fdopen(pfd[1], type)) == NULL)

return(NULL);

}

childpid[fileno(fp)] = pid; /* remember child pid for this fd */

return(fp);

}

int

pclose(FILE *fp)

{

int     fd, stat;

pid_t   pid;

if (childpid == NULL) {

errno = EINVAL;

return(-1);     /* popen() has never been called */

}

fd = fileno(fp);

if ((pid = childpid[fd]) == 0) {

errno = EINVAL;

return(-1);     /* fp wasn‘t opened by popen() */

}

childpid[fd] = 0;

if (fclose(fp) == EOF)

return(-1);

while (waitpid(pid, &stat, 0) < 0)

if (errno != EINTR)

return(-1); /* error other than EINTR from waitpid() */

return(stat);   /* return child‘s termination status */

}

时间: 2024-10-16 23:20:34

popen 函数的相关文章

popen函数的用法及注意事项

标准I/O库提供了两个函数popen和pclose这两个函数,它们的功能是创建一个连接到另一个进程的管道,然后读其输出或向其输入端发送数据.先fork一个子进程,关闭未使用的管道端. popen() 函数 用 创建管道 的 方式启动一个 进程, 并调用 shell. 因为 管道是被定义成单向的, 所以 type 参数 只能定义成 只读或者 只写, 不能是 两者同时, 结果流也相应的 是只读 或者 只写. 函数popen的原型: FILE* POPEN(const char* cmdstring,

Linux popen()函数详解

表头文件 #include<stdio.h> 定义函数 FILE * popen( const char * command,const char * type); 函数说明 popen()会调用fork()产生子进程,然后从子进程中调用/bin/sh -c来执行参数command的指令.参数type可使用“r”代表读取,“w”代表写入.依照此type值,popen()会建立管道连到子进程的标准输出设备或标准输入设备,然后返回一个文件指针.随后进程便可利用此文件指针来读取子进程的输出设备或是写

UNIX环境高级编程之-----popen函数

头文件: #include <stdio.h> 函数说明: FILE * popen ( const char * command , const char * type ); int pclose ( FILE * stream ); 说明:(参考unix环境高级编程) popen() 函数通过创建一个管道,调用 fork 产生一个子进程,执行一个 shell 以运行命令来开启一个进程.这个进程必须由 pclose() 函数关闭,而不是 fclose() 函数.pclose() 函数关闭标准

linux下C和shell调用的popen函数

说明: 本文介绍popen函数的使用方法和行为机理,并给出实际的例子来辅助说明了popen函数的使用方法. popen函数使用FIFO管道执行外部程序,首先让我们看看popen的函数原型吧: #include <stdio.h> FILE *popen(const char *command, const char *type); int pclose(FILE *stream); popen 通过type是r 还是w 来确定command的输入/输出方向,r和w是相对command的管道而言

linux popen函数

函数原型 FILE *popen(const char *command, const char *type); int pclose(FILE *stream); 函数说明 popen()函数通过创建一个管道,调用fork()产生一个子进程,执行一个shell以运行命令来开启一个进程.这个管道必须由pclose()函数关闭,而不是fclose()函数.pclose()函数关闭标准I/O流,等待命令执行结束,然后返回shell的终止状态.如果shell不能被执行,则pclose()返回的终止状态

C 语言popen函数,实现shell和读取内容

1. popen()函数 头文件:#include <stdio.h> 函数原型:FILE * popen(const char * command, const char * type); 关闭文件流:int pclose(FILE * stream); 函数popen 先执行fork,然后调用exec以执行cmd,并且返回一个标准I/O文件指针. cmd是一个包含shell命令的字符串指针(以NULL结束字符结尾): 如果type是"r",则文件指针连接到cmd的标准输

os.system和os.popen函数

os.system和os.popen函数: python调用shell命令有2种方法:os.system()和os.popen() os.system()的返回值只会有0(成功),1,2:os.popen()会把执行命令的输出作为值返回,可实现一个"管道",从这个命令获取的值可以继续被调用. 示例: vi a1.py #!/usr/bin/python import os a = os.popen('df -h /').readlines()a2 = ''.join(a)print a

【IPC通信】基于管道的popen和pclose函数

http://my.oschina.net/renhc/blog/35116 恋恋美食  恋恋美食 发布时间: 2011/11/12 23:20 阅读: 15897 收藏: 13 点赞: 5 评论: 0 标准I/O函数库提供了popen函数,它启动另外一个进程去执行一个shell命令行. 这里我们称调用popen的进程为父进程,由popen启动的进程称为子进程. popen函数还创建一个管道用于父子进程间通信.父进程要么从管道读信息,要么向管道写信息,至于是读还是写取决于父进程调用popen时传

管道通信(使用使用popen和pclose函数可以简洁的控制管道)

函数原型: FILE *popen(const char * command ,const char *mode) int pclose(FILE * stream) 注意点: 使用popen和pclose函数可以简洁的控制管道,不需要更多的代码, 但是降低了程序员对管道的控制能力 参数commend是shell命令 参数mode是一个字符指针,r或W,分别表示popen函数的返回值是一个读打开文件指针,还是写打开文件指针,失败时返回值为NULL, 并设置出错变量errno 代码实例: pope