linux 关闭popen 打开的命令

程序设计了一个图形界面用于开了一个线程执行终端命令,通过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);
}

解决了问题、保持在图形界面上只执行一个命令进程并显示命令结果



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值