linux 函数 :popen(),system(),wsystem() (***)

目录

popen是什么意思?
Linux中system()函数与popen()函数 (*)
linux system()函数完全解密
linux popen()函数完全解密
C 语言popen函数,逐行读取shell命令内容
基于管道的popen和pclose函数
popen() 使用举例 (转载)
popen函数 Qt

-------------------------------------------------------

https://blog.csdn.net/ken2232/article/details/130316198
QString::toWCharArray 与 宽字符路径、空格 (测试OK)(***)

------------------------------

比较:

popen():popen(命令, "r"),直接支持宽字符。宽字符文件路径,与_wsystem相比,使用popen似乎最简单?

_wsystem():_wsystem(L“宽字符串命令”),支持宽字符。为 win OS 下的app,linux不能用?!

system():只支持 latin1。

==================================

学习笔记——popen()函数详解

https://blog.csdn.net/qq_44333320/article/details/124875059

popen()函数

引用度娘说的:
popen() 函数通过创建一个管道,调用 fork 产生一个子进程,执行一个 shell 以运行命令来开启一个进程。

这个进程必须由 pclose() 函数关闭,而不是 fclose() 函数。pclose() 函数关闭标准 I/O 流,等待命令执行结束,然后返回 shell 的终止状态。如果 shell 不能被执行,则 pclose() 返回的终止状态与 shell 已执行 exit 一样。

也就是,popen创建管道,执行shell命令将文件流中的某些数据读出

看看man手册
NAME
       popen, pclose - pipe stream to or from a process

SYNOPSIS
       #include <stdio.h>//头文件

      FILE *popen(const char *command, const char *type);//原型

参数说明:

command: 是一个指向以 NULL 结束的 shell 命令字符串的指针。命令将被传到 bin/sh 并使用 -c 标志,shell 将执行这个命令,比如sh -c ls

type: 只能是读或者写中的一种,得到的返回值(标准 I/O 流)也具有和 type 相应的只读或只写类型。如果 type 是 “r” 则文件指针连接到 command 的标准输出;如果 type 是 “w” 则文件指针连接到 command 的标准输入

返回值:
如果调用 fork() 或 pipe() 失败,或者不能分配内存将返回NULL,否则返回一个读或者打开文件的指针。
————————————————
版权声明:本文为CSDN博主「石子君」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_44333320/article/details/124875059

system(3) — Linux manual page

https://man7.org/linux/man-pages/man3/system.3.html

SYNOPSIS  

       #include <stdlib.h>

       int system(const char *command);

=======================

popen是什么意思?

popen == opens a process == process opens ??

popen

DESCRIPTION

       The popen() function opens a process by creating a pipe, forking,
       and invoking the shell.  Since a pipe is by definition
       unidirectional, the type argument may specify only reading or
       writing, not both; the resulting stream is correspondingly read-
       only or write-only.

https://www.man7.org/linux/man-pages/man3/popen.3.html

popen函数 Qt

pclose(fp);  //记得释放资源

popen函数使用示例

环境:CentOS7.6  Qt 5.9.4
 QSring strCmd = "cat /proc/cpuinfo |grep MHz|uniq\n";
 FILE* fp = popen(strCmd.toLocal8Bit().data(), "r");
 if (nullptr != fp)
 {
       char buf[1024] = {0};
       char result[2000] = {0};
       while (fgets(buf, sizeof(buf), fp))
      {
              strcat(result, buf);
             if (strlen(result) > sizeof(buf))
            {
                   break;
            }
       }
       pclose(fp);  //记得释放资源
       fp = nullptr;

 //result即为执行终端命令“cat /proc/cpuinfo |grep MHz|uniq”得到的结果
 //后续可对result 进行其他处理
 }

popen() 使用举例 (转载)

popen() 使用举例 (转载)_diedie4488的博客-CSDN博客

函数原型:

  #include “stdio.h”

  FILE *popen( const char* command, const char* mode )

  参数说明:

  command: 是一个指向以 NULL 结束的 shell 命令字符串的指针。这行命令将被传到 bin/sh 并使用 -c 标志,shell 将执行这个命令。

  mode: 只能是读或者写中的一种,得到的返回值(标准 I/O 流)也具有和 type 相应的只读或只写类型。如果 type 是 “r” 则文件指针连接到 command 的标准输出;如果 type 是 “w” 则文件指针连接到 command 的标准输入。

  返回值:

  如果调用成功,则返回一个读或者打开文件的指针,如果失败,返回NULL,具体错误要根据errno判断

  int pclose (FILE* stream)

  参数说明:

  stream:popen返回的文件指针

  返回值:

  如果调用失败,返回 -1

  作用:

  popen() 函数用于创建一个管道:其内部实现为调用 fork 产生一个子进程,执行一个 shell 以运行命令来开启一个进程这个进程必须由 pclose() 函数关闭。

基于管道的popen和pclose函数

基于管道的popen和pclose函数_pclose return 256_路飞大大的博客-CSDN博客

标准I/O函数库提供了popen函数,它启动另外一个进程去执行一个shell命令行

这里我们称调用popen的进程为父进程,由popen启动的进程称为子进程。

popen函数还创建一个管道用于父子进程间通信。子进程要么从管道读信息,要么向管道写信息,至于是读还是写取决于父进程调用popen时传递的参数。下在给出popen、pclose的定义:

C 语言popen函数,逐行读取shell命令内容

1. popen()函数

头文件:#include <stdio.h>

函数原型:FILE * popen(const char * command, const char * type);

关闭文件流:int pclose(FILE * stream);

函数popen 先执行fork,然后调用exec以执行cmd,并且返回一个标准I/O文件指针。

cmd是一个包含shell命令的字符串指针(以NULL结束字符结尾);
如果type是"r",则文件指针连接到cmd的标准输出;
如果type是"w",则文件指针连接到cmd的标准输入。
2. 描述

popen() 函数用创建管道的方式启动一个进程, 并调用 shell. 因为管道是被定义成单向的, 所以type参数只能定义成只读或者只写, 不能是两者同时, 结果流也相应的是只读或者只写.

command 参数是一个字符串指针, 指向的是 一个以 null 结束符结尾的字符串, 这个字符串包含一个 shell 命令. 这个命令被送到 /bin/sh 以 -c 参数执行, 即由 shell 来执行. type 参数也是一个 指向以 null 结束符结尾的字符串的指针, 这个字符串必须是 'r' 或者 'w’ 来指明是读还是写.

  popen() 函数的返回值是一个普通的标准I/O流, 它只能用 pclose() 函数来关闭, 而不是 fclose() 函数.

注意, popen 函数的输出流默认是被全缓冲的;pclose 函数等待相关的进程结束并返回一个 command 命令的退出状态, 就像 wait4 函数 一样
————————————————
版权声明:本文为CSDN博主「smartvxworks-V2」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/smartvxworks/article/details/128957587

linux popen()函数完全解密

https://zhuanlan.zhihu.com/p/457974696

linux system()函数完全解密

https://zhuanlan.zhihu.com/p/457019360

为什么很多网友和技术大佬都推荐使用它替代system()来使用呢?

====================================

Linux中system()函数与popen()函数 (*)

http://laihaodong.cn/2061.html

1. system()

程序可以通过调用 system() 函数来执行任意的shell命令。同样这个Shell命令执行的输出会打印在终端上。\

#include <stdlib.h>
int system(const char* command);

C

system()库函数通过fork出一个子进程,并且让子进程通过execl()程序替换来执行对应的 shell 命令。问题是替换成什么程序可以执行shell命令呢?答案是 /bin 目录下的sh程序。sh -c command即可执行指定的命令。sh 其实就是一个shell程序,在我的系统中 sh 是一个指向 dash 的软链接,所以system()的真正执行步骤应该是:调用system(),函数内部创建了一个子进程并替换成 shell 程序,而 shell 程序执行一条命令的步骤同样是创建一个子进程,并让子进程替换成需要执行的 command,所以可以看到system()运行期间总共存在三个进程。下图展现了用system()执行sleep命令的步骤:

system()当命令执行完毕才会返回,也就是阻塞函数。

在命令执行期间,SIGCHLD信号将被阻塞,SIGINT和SIGQUIT信号将被忽略。

如果 command 为NULL,则system()返回一个表示当前系统是否有可用shell的状态。

2. 基本的 system() 实现

先按照文档的描述来实现一个简单的system()函数,这其实就是对Linux编程的基本知识如创建子进程、进程等待、进程替换的一个综合运用。

int my_system(const char* command) {
    pid_t pid = fork();
    int status;

    switch(pid) {
    case -1: 
        return -1; 
    case 0:  // child
        execl("/bin/sh", "sh", "-c", command, NULL);
        exit(-1);  // execl error
    default:  // parent
        waitpid(pid, &status, 0); 
        return status;
    }   
}

C

3. popen() : 通过管道与Shell命令进行通信

popen()system()的功能类似,同样是执行一条Shell命令。但popen()使用了管道来读取Shell命令的输出或者是通过管道来给Shell命令传递输入。

#include <stdio.h>
FILE* popen(const char* command, const char* mode);
int pclose(FILE* stream);

C

popen()函数创建了一个管道,然后创建一个子进程来执行Shell,而Shell同样需要创建一个子进程来执行指定的Shell命令。这个过程类似于system()。mode 参数是一个字符串,它确定函数的调用者是从管道中读取 Shell 命令的输出(mode为 r ),还是通过管道给Shell命令传递输入(mode为 w )。(由于单个管道只支持单向信息传输,所以必须在创建管道之前就确定数据传输方向)。下图展示了两种mode取值的不同之处:

popen()返回了该管道的操作句柄,即一个文件流指针,函数调用者可以通过这个操作句柄来和Shell命令进行通信。这也点出了popen()system()的不同之处,即system()是一个阻塞函数,Shell命令执行完成之前不会返回,用户通过终端与Shell命令交互。而popen()是一个非阻塞函数,它在建立一个子进程并执行程序替换sh -c command之后会立刻返回,而不等待Shell程序的终止。用户通过主程序与Shell命令进行通信。即可以总结为popen()的调用进程与Shell命令进程是并行执行的。

由于使用的是管道,所以与 pipe 创建出的管道有相同的读写特性,即管道写端关闭后尝试读会返回0,管道读端关闭后尝试写会受到 SIGPIPE 信号而被杀死。

一旦 I/O 结束后可以使用pclose()函数关闭管道,并且该函数会等待Shell程序终止才返回。而pclose()的返回值为Shell进程的终止状态,即 wait 所得到的状态。

4. 基本的popen() 实现

#include <stdio.h>                                                                                                                      
#include <unistd.h>
#include <stdlib.h>

FILE* my_popen(const char* command, const char* type) {
    FILE* fp; 

    // if type is invalid
    if((type[0] != 'w' && type[0] != 'r') || type[1] != '\0') {
        return NULL;
    }   

    int pipefd[2];
    pipe(pipefd);

    pid_t pid = fork();
    switch(pid) {
        case -1: 
            perror("fork error");
            exit(0);
        case 0:  // child
            if(type[0] == 'w') {
                close(pipefd[1]);
                dup2(pipefd[0], STDIN_FILENO);
                close(pipefd[0]);  // close extra read end
            }   
            else if(type[0] == 'r') {
                close(pipefd[0]);
                dup2(pipefd[1], STDOUT_FILENO);
                close(pipefd[1]);  // close extra write end
            }   

            execl("/bin/sh", "sh", "-c", command, NULL);
            exit(-1);
        default:  // parent
            if(type[0] == 'r') {
                close(pipefd[1]);
                fp = fdopen(pipefd[0], type);
            }
            else {
                close(pipefd[0]);
                fp = fdopen(pipefd[1], type);
            }

            return fp;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值