The standard I/O function library provides the Popen function, which initiates another process to execute a shell command line.
Here we call the process calling Popen the parent process, and the process initiated by Popen is called a child process.
The Popen function also creates a pipeline for inter-parent interprocess communication. The parent process either reads information from the pipeline, or writes information to the pipeline, whether it is read or write, depending on the parameters passed when the parent process calls Popen. The definition of Popen and Pclose is given below:
03 |
函数功能:popen()会调用fork()产生子进程,然后从子进程中调用/bin/sh -c来执行参数command的指令。 |
04 |
参数type可使用“r”代表读取,“w”代表写入。 |
05 |
依照此type值,popen()会建立管道连到子进程的标准输出设备或标准输入设备,然后返回一个文件指针。 |
06 |
随后进程便可利用此文件指针来读取子进程的输出设备或是写入到子进程的标准输入设备中 |
07 |
返回值:若成功则返回文件指针,否则返回NULL,错误原因存于errno中 |
09 |
FILE * popen( const char * command, const char * type); |
12 |
函数功能:pclose()用来关闭由popen所建立的管道及文件指针。参数stream为先前由popen()所返回的文件指针 |
13 |
返回值:若成功返回shell的终止状态(也即子进程的终止状态),若出错返回-1,错误原因存于errno中 |
15 |
int pclose( FILE * stream); |
The following example looks at the use of Popen:
If we want to get the number of files in the current directory, under the shell we can use:
We can write this in the program:
11 |
char result_buf[MAXLINE], command[MAXLINE]; |
12 |
int rc = 0; // 用于接收命令返回值 |
16 |
snprintf(command, sizeof (command), "ls ./ | wc -l" ); |
18 |
/*执行预先设定的命令,并读出该命令的标准输出*/ |
19 |
fp = popen(command, "r" ); |
25 |
while ( fgets (result_buf, sizeof (result_buf), fp) != NULL) |
27 |
/*为了下面输出好看些,把命令返回的换行符去掉*/ |
28 |
if ( ‘\n‘ == result_buf[ strlen (result_buf)-1]) |
30 |
result_buf[ strlen (result_buf)-1] = ‘\0‘ ; |
32 |
printf ( "命令【%s】 输出【%s】\r\n" , command, result_buf); |
35 |
/*等待命令执行完毕并关闭管道及文件指针*/ |
44 |
printf ( "命令【%s】子进程结束状态【%d】命令返回值【%d】\r\n" , command, rc, WEXITSTATUS(rc)); |
Compile and execute:
$ gcc POPEN.C
$./a.out
Command "ls./| Wc-l "Output" 2 "
Command "ls./| Wc-l "Child process End State" 0 "command return value" 0 "
The above Popen only captures the command's standard output, and if command execution fails, the child process prints the error message to the standard error output and the parent process cannot get it. For example, the command is "LS nofile.txt", in fact we do not nofile.txt this file at all, when the shell will output "Ls:nofile.txt:No such file or directory". This output is on the standard error output. It cannot be obtained through the above program.
Note: If you set the command in the above program to "LS Nofile.txt", compile the execution program and you will see the following result:
$ gcc POPEN.C
$./a.out
Ls:nofile.txt:No such file or directory
Command "LS nofile.txt" child process End Status "256" command return value "1"
It is important to note that the first line of output is not the output of the parent process, but the standard error output of the child process.
Sometimes the error message of a child process is useful, so how can the parent process get the error message of the child process?
Here we can redirect the error output of the child process and redirect the error output to standard output (2>&1) so that the parent process can capture the error message of the child process. For example, the command is "LS nofile.txt 2>&1" and the output is as follows:
Command "LS nofile.txt 2>&1" output "Ls:nofile.txt:No such file or directory"
Command "LS nofile.txt 2>&1" Child process End Status "256" command return value "1"
Attached: The termination state of the child process to determine the macro involved, set the status of the process to terminate.
Wifexited (status) is a non-0 value if the child process ends normally.
Wexitstatus (status) Gets the end code returned by the child process exit (), typically using wifexited to determine whether the macro ends properly before it can be used.
wifsignaled (status) This macro value is true if the child process ends because of a signal.
Wtermsig (status) Gets the signal code that the child process aborts because of the signal, generally uses wifsignaled to judge before using this macro.
wifstopped (status) This macro value is true if the child process is in a paused execution condition. This is generally the case only if you are using wuntraced.
Wstopsig (status) Gets the signal code that causes the child process to pause, usually using wifstopped to judge before the macro is used.
Popen and Pclose functions for "IPC communication" based on pipelines