我在下面有一个脚本,用于指示将来自/dev/ttyUSB1
的数据重定向到文件。
#!/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 :(得分:1)
我将什么作为参数传递给它?
该函数接受指向整数(int*
)的指针并写入这些整数地址,因此您需要有两个整数并传递它们的地址,如下所示:
int input, output; // input and output file descriptors
int pid = system2("script args", &input, &output);
答案 1 :(得分:1)
你对这个问题采取了错误的方法。
使用fork
/ exec
和管道发布的示例代码是运行外部命令并读取其输出的正确方法。但是,您运行的命令是cat
。所有这一切都是读取文件并输出。
因此,不要启动单独的流程来调用cat
,只需打开文件并从中读取:
FILE *fp = fopen("/dev/ttyUSB1", "r");
if (!fp) {
perror("open failed");
exit(1);
} else {
// read from file
...
}
答案 2 :(得分: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>
进程,期望父进程等待它们完成,它可以检查他们的退出状态。在这种情况下,我们对任何返回代码都不感兴趣,所以我们让它们立即死亡。