[英]subprocess.popen (python) in C
就像問題說的那樣,我正在C
搜索subprocess.open module
。
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, preexec_fn=os.setsid)
print p.pid
我正在嘗試生成一個進程,然后獲取該進程的ID。
`cmd` is a c program that is spawned
在C語言中,我相信getpid()
完成這項工作。
但是,在生成進程之后,我不知道如何告訴getpid()
來獲取該生成的進程pid。
void run_apps(pid) {
printf("process ID is %d\n", (int) getpid());
}
那顯然是給出當前的進程ID。
在C語言中,首先調用fork()
創建一個新進程(最終是子進程),然后調用exec*()
函數家族之一來執行該子進程,從而獲得最大數量的選項。 原始進程和新進程都將同時運行,因此您可以通過管道或套接字對交換(讀取和/或寫入數據)。 最后,在循環中使用例如waitpid()
來等待新進程退出,並“獲取”其退出狀態。 例如:
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
int main(void)
{
pid_t child, p;
int status;
/*
* Prepare pipes et cetera first.
*/
/* Fork to create the subprocess. */
child = fork();
if (child == (pid_t)-1) {
/* Cannot fork(); usually out of resources (user limits).
* see errno for details. With <string.h>, you can use
* strerror(errno) to obtain the error string itself. */
return 1;
} else
if (!child) {
/* This is the child process itself.
* Do whatever cleanup is necessary, then
* execute the subprocess command. */
execlp("/bin/ls", "ls", "-lA", NULL);
/* This is only reached if the exec failed;
* again, see errno for reason.
* Always have the child process exit! */
return 127;
}
/* This is only run by the parent process
* (because the child always exits within the
* else if body above).
*
* The subprocess PID is 'child'.
*/
/* Wait for the child process to exit. */
do {
status = 0;
p = waitpid(child, &status, 0);
if (p == (pid_t)-1 && errno != EINTR)
break; /* Error */
} while (p != child);
if (p != child) {
/* Child process was lost.
* If (p == (pid_t)-1), errno describes the error.
*/
} else
if (WIFEXITED(status)) {
/* Child process exited with WEXITSTATUS(status) status.
* A status of 0 (or EXIT_SUCCESS) means success,
* no errors occurred. Nonzero usually means an error,
* but codes vary from binary to binary.
*/
} else
if (WIFSIGNALED(status)) {
/* Child process died from WTERMSIG(status) signal.
* If you include <string.h>, you can use
* strsignal(WTERMSIG(status))
* to obtain the name (string) of the terminating signal.
*/
} else {
/* Child process died from unknown causes.
*/
}
/* All done. */
return 0;
}
就個人而言,我更喜歡使用socketpair()
在我控制的進程之間創建Unix域流或數據報套接字,如果子進程只是一些要運行的隨機二進制文件,則可以通過pipe()
創建pipe()
。 在所有情況下,都可以使用dup2()
函數用套接字或管道替換標准輸入( STDIN_FILENO
描述符),標准輸出( STDOUT_FILENO
描述符)和標准錯誤( STDERR_FILENO
描述符)。 您甚至可以從父級訪問/proc/[child]/
下的偽文件,以觀察子進程的狀態。
根據您與子流程進行通信的方式-文件的輸入/輸出? 內存中的字符串? 動態分配用於輸出的緩沖區-有很多變體。 當需要精確控制和/或全雙工(讀和寫)和/或異步通信時,通常使用與上面類似的代碼。
您可以在自己喜歡的搜索引擎中搜索“ linux”,“ fork”,“ exec” ,以獲得各種質量的示例。
如果您想要一個更簡單的解決方案,並且只需要捕獲命令的輸出(不向命令提供任何輸入,或者從文件中提供輸入),則可以使用
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
int main(void)
{
FILE *sub;
pid_t subpid;
int status;
sub = popen("setsid /bin/sh -c 'echo $$ ; exec command args' </dev/null", "rb");
if (!sub) {
/* popen() failed. */
return 1;
}
/* Read the first line from sub. It contains the PID for the command. */
{
char buffer[32], *line, dummy;
int value;
line = fgets(buffer, sizeof buffer, sub);
if (!line) {
/* setsid failed, or non-POSIXy system (Windows?) */
pclose(sub);
return 1;
}
if (sscanf(line, "%d%c", &value, &dummy) != 1 || value < 2) {
/* Internal bug, or extra output? */
pclose(sub);
return 1;
}
/* subpid is also the session ID and the process group ID,
* because it is the session leader. */
subpid = value;
}
/* Read from sub using standard I/O, to capture command output. */
/* After no more output to read from sub, reap the subprocess. */
errno = 0;
do {
status = pclose(sub);
} while (status == -1 && errno == EINTR);
if (status) {
/* Problem: sub exited with nonzero exit status 'status',
* or if status == -1, some other error occurred. */
} else {
/* Sub exited with success (zero exit status). */
}
/* Done. */
return 0;
}
在Linux中, popen()
使用/bin/sh
shell(按照POSIX.1規范),並且我們可以使用setsid
命令行實用程序來創建新會話。 在該命令中, echo $$
是一個sh
命令,它輸出shell PID,然后exec CMD...
用該命令替換shell; 因此我們甚至在執行命令之前就獲得了命令的PID。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.