函數原型:
#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.
中文總結:
popen函數是通過建立一個管道的方式打開一個程序,并調用shell。因為管道是被定義為單向的,是以type的值隻能是r或w其中的一個,結果流也是如此。
command(指令行/指令的意思)參數:是一個以NULL結尾的字元串,這個字元串應是一個shell指令。這個指令會被送到 /bin/sh中,并以 -c執行即被shell執行。
type參數:隻能是r或w中的一個,r或w是相當command管道而言的。r表示從command管道中讀,w表示通過command管道輸出到stdout中(輸出流為全緩沖)。
傳回值:如果fork或者pipe失敗,或者不能配置設定到記憶體都會傳回NULL,成功則傳回标志I/O流。popen沒有為申請記憶體失敗設定errno值,但fork和pipe都有其相應的errno值。如果type參數不合法,errno會别設定為EINVAL.
注意:隻能用pclose函數進行關閉操作,不能用fclose。
相關代碼:
type為 r時:
#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;
}
執行結果:
<a href="http://s1.51cto.com/wyfs02/M02/7E/ED/wKiom1cM25WiarsQAABpPzqeJMM765.png" target="_blank"></a>
當type為 w 時:(此時popen函數會通過FIFO管道直接向stdout中寫資料)
stream = popen("ls -l","w");
if(stream == NULL)
{
perror("popen");
return -1;
}
pclose(stream);
<a href="http://s1.51cto.com/wyfs02/M01/7E/EA/wKioL1cM3t3SYSpqAABKBRBo5j8839.png" target="_blank"></a>
注意:一個執行的指令是 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)
} else {
close(pfd[0]);
if ((fp = fdopen(pfd[1], type)) == NULL)
childpid[fileno(fp)] = pid; /* remember child pid for this fd */
return(fp);
}
int
pclose(FILE *fp)
int fd, stat;
if (childpid == NULL) {
errno = EINVAL;
return(-1); /* popen() has never been called */
fd = fileno(fp);
if ((pid = childpid[fd]) == 0) {
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 */
本文轉自 ye小灰灰 51CTO部落格,原文連結:http://blog.51cto.com/10704527/1763143,如需轉載請自行聯系原作者