程序设计了一个图形界面用于开了一个线程执行终端命令,通过pope打开一个管道来执行命令,
此时需要循环读取程序执行的结果。
void* command_exec(void* cmdstr)
{
FILE *cmdStream=NULL;
char *cmd = (char *)cmdstr;
char buff[200];
if(NULL==(cmdStream=popen(cmd,"r")))
{
fprintf(stderr,"execute command failed: %s",strerror(errno));
pthread_exit(NULL);
}
while(fgets(buff,200, cmdStream)!=NULL)
{
g_printf("%s\n", buff);
}
pclose(cmdStream);
pthread_exit(NULL);
}
由于命令一直都在执行,一直在while循环中 , 该线程不能结束,此时需要结束命令,通过pthread_kill结束线程来实现发现命令所起的进程并没有关闭,而且cmdSream文件流也没有正常close, 最后通过信号处理函数
void command_exit() {
if(cmdStream != NULL) {
pclose2(cmdStream);
cmdStream = NULL;
pthread_exit((void *)2);
}
}
关闭了管道,但是命令进程还是存在着,最后通过修改popen , pclose 函数源码自己实现结束进程来完成。
修改后的函数如下,在pclose 中添加了kill
#define SHELL "/bin/bash"
static pid_t *childpid=NULL; /*ptr to array allocated at run-time*/
static int maxfd; /*from our open_max(), {Prox openmax}*/
FILE *popen2(const char *cmdstring, const char *type)
{
int i, pfd[2];
pid_t pid;
FILE *fp;
/*only allow "r" or "w"*/
if(type[0] != 'r' && type[0]!='w' || type[1] != 0) {
errno=EINVAL;
return (NULL);
}
if(childpid == NULL) { /*first time throngh, allocate zeroed out array for child pids*/
maxfd = sysconf(_SC_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); //error 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 descriptiors in childpid*/
for(i = 0; i < maxfd; i++)
if(childpid[i] > 0)
close(i);
execl(SHELL, "bash", "-c", cmdstring, (char *)0);
_exit(127);
}
/*parent*/
if(*type == 'r') {
close(pfd[1]);
if((fp = fdopen(pfd[0], type)) == NULL)
return (NULL);
}else {
close(pfd[0]);
if((fp = fdopen(pfd[1], type)) == NULL)
return (NULL);
}
childpid[fileno(fp)] = pid; /*remember child pid for this fd*/
return(fp);
}
int pclose2(FILE *fp)
{
int fd, stat;
pid_t pid;
printf("hello>>>>>>>>>>>>>\n");
if(childpid == NULL) /*popen() has never benn called*/
return (-1);
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);
if( kill(pid, SIGKILL) != 0) {
printf("kill failed\n");
perror("kill");
}
else {
printf("%d killed\n", pid);
}
while(waitpid(pid, &stat, 0) < 0) {
if(errno != EINTR )
return (-1); /*error other than EINTR from waitpid()*/
}
return(stat);
}
解决了问题、保持在图形界面上只执行一个命令进程并显示命令结果