2017-07-27 180 views
1

我在下面有一个脚本,它指示将来自/dev/ttyUSB1的数据重定向到文件。如何获得在c程序中使用system()启动的进程的PID

#!/bin/bash 
# start minicom with file name of todays date 
cat /dev/ttyUSB1 > ~/serial_logs/$1.txt & 

我把这个脚本使用system()一个C程序,它创建与当前日期和时间的文件。

//Get string with date & time 
//Open minicom with logging to filename with date and time 
strftime(s, sizeof(s), "%a%b%d%T", tm); 
snprintf(buf, SM_BUF, "~/logging.sh %s",s); 
system(buf); 

但是在稍后的c程序中,我需要杀死这个进程。 System()不返回cat进程的PID。

我碰到过this post这暗示使用下面的函数,但是我不清楚我如何使用它。

我的问题基本上是我作为参数传递给它什么?

pid_t system2(const char * command, int * infp, int * outfp) 
{ 
    int p_stdin[2]; 
    int p_stdout[2]; 
    pid_t pid; 

    if (pipe(p_stdin) == -1) 
     return -1; 

    if (pipe(p_stdout) == -1) { 
     close(p_stdin[0]); 
     close(p_stdin[1]); 
     return -1; 
    } 

    pid = fork(); 

    if (pid < 0) { 
     close(p_stdin[0]); 
     close(p_stdin[1]); 
     close(p_stdout[0]); 
     close(p_stdout[1]); 
     return pid; 
    } else if (pid == 0) { 
     close(p_stdin[1]); 
     dup2(p_stdin[0], 0); 
     close(p_stdout[0]); 
     dup2(p_stdout[1], 1); 
     dup2(::open("/dev/null", O_RDONLY), 2); 
     /// Close all other descriptors for the safety sake. 
     for (int i = 3; i < 4096; ++i) 
      ::close(i); 

     setsid(); 
     execl("/bin/sh", "sh", "-c", command, NULL); 
     _exit(1); 
    } 

    close(p_stdin[0]); 
    close(p_stdout[1]); 

    if (infp == NULL) { 
     close(p_stdin[1]); 
    } else { 
     *infp = p_stdin[1]; 
    } 

    if (outfp == NULL) { 
     close(p_stdout[0]); 
    } else { 
     *outfp = p_stdout[0]; 
    } 

    return pid; 
} 
+0

重复这个https://stackoverflow.com/questions/22802902/how-to-get-pid-of-process-executed-with-system-command-in-c? – fghj

+0

[如何获得用C++中的system()命令执行的进程的pid](https:// stackoverflow。com/questions/22802902 /如何获得进程的执行与系统命令在c) – fghj

+0

@MarkPlotnick是的抱歉,我正在寻找猫进程的PID。 – riverrock

回答

0

我作为参数传递给了什么?

函数接受指向整数(int*),并写入这些整数地址,因此你需要有两个整数,并通过他们的地址是这样的:

int input, output; // input and output file descriptors 
int pid = system2("script args", &input, &output); 
0

你正在做完全错了解决这个问题。

您使用fork/exec发布的示例代码和管道是运行外部命令并读取其输出的正确方法。但是,您正在运行的命令是cat。所有这些都是读取文件并输出。

因此,而不是启动一个单独的进程调用cat,只需打开该文件,并从中读取:

FILE *fp = fopen("/dev/ttyUSB1", "r"); 
if (!fp) { 
    perror("open failed"); 
    exit(1); 
} else { 
    // read from file 
    ... 
} 
+0

这听起来像OP希望阅读(和写入文件)在“背景”发生,将在未来的某个点被杀害。所以即使他们替换了'cat',他们仍然需要在代码的fork分支中进行读写操作。 – TripeHound

+0

嗨@dbush,感谢您的有用评论。 @TripeHound是我想要的只是从串行端口开始读取一个文件,然后稍后停止读取文件。因此,为了做到这一点,我需要知道cat进程的PID,以便我可以使用'system()'和'pkill'从c程序中杀死它。 – riverrock

+1

@riverrock我无法将任何代码放在一起,但你应该能够使用'fork'来创建一个子进程(返回一个PID),而不是执行'cat',只是让它循环反复读取USB1并写入文件。同时,父母程序可以做它所需要的,并在需要时杀死孩子。 – TripeHound

0

虽然你可以使用fork()/exec()启动外部命令(同时获取PID)如@dbush's answer指出的那样,您需要的操作(从一个文件读取并写入另一个文件)非常简单,您可以在代码中执行此操作。但是,既然你想让它在后台运行,直到主代码决定停止它,你的仍然需要使用fork()。下面的代码显示的基本思路:

#include <stdio.h> 
#include <signal.h> 

int main() 
{ 
    // Prevent killed child-processes remaining as "defunct" 
    struct sigaction sigchld_action = { 
     .sa_handler = SIG_DFL, 
     .sa_flags = SA_NOCLDWAIT 
    }; 
    sigaction(SIGCHLD, &sigchld_action, NULL) ; 

    // Duplicate ("fork") the process. Will return zero in the child 
    // process, and the child's PID in the parent (or negative on error). 
    int pid = fork() ; 
    if(pid < 0) { 
     printf("Fork failed\n") ; 
     return 1 ; 
    } 

    if(pid == 0) { 
     // ------------ Child process 
     // Here is where you'd open "/dev/ttyUSB1" and the output file 
     // and continually read data from one and write it to the other. 
     while(1) { 
      printf("child process\n") ; 
      sleep(1) ; 
     } 
     return 0 ; //never reached 
    } 

    // ------------ Parent process 
    // Here is where you'd do whatever the main program needs to do. 
    printf("Main program\n") ; 
    sleep(10); 

    // When you are ready, it can kill the child process 
    printf("Killing child\n") ; 
    kill(pid, SIGTERM) ; 

    printf("Finished\n") ; 
    return 0 ; 
} 

实际执行的读写的就留给读者做练习。

注意:如果没有在代码顶部的sigaction调用,子进程将保持为<defunct>进程,期望父进程将等待它们完成,以便检查它们的退出状态。在这种情况下,我们对任何返回码都不感兴趣,所以我们立即让它们死亡。

相关问题