创建子进程去执行另外一个程序的三种方法

本文介绍三种在程序中执行另一个程序的方法:使用fork()+exec()函数组合、system()函数及popen()函数。这些方法可用于获取子进程的输出并进一步处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

有时候在写代码的时候我们会需要一个程序的执行结果,这个时候我们可以通过本文的三种方法,使用子进程来运行该程序,并把运行结果重定向到文件(或者不需要这一步),然后就能某一个程序的运行结果,并在该代码中进行处理了。


提示:以下是本篇文章正文内容,下面案例可供参考

一、fork()函数 + exec()函数

在上一篇文件中讲的fork()函数,都是让子进程执行父进程的文本段,更多的情况下是让子进程执行另外一个程序。下面这个例子就是通过标题中的两个函数实现在子进程中执行另一个程序的。

代码示例如下:

 #include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>

//标准输出重定向的文件
#define TMP_FILE1       "/tmp/.ifconfig.log"

int main(int argc,char ** argv)
{

        //变量的定义
        int             fd;
        pid_t           pid;
        int             rv;
        char            buf[1024];
        //父进程打开这个进程,子进程会继承父进程的文件描述符,所以父子进程可以通过各自的文件>描述符来访问同一个文件了
        if((fd = open(TMP_FILE1,O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0)
        {
                printf("redirect standard output to file failure:%s\n",strerror(errno));
                return -1;
                //打开(创建)文件出错就输出提示信息
        }
        //父进程开始创建子进程
        pid = fork();
        if(pid < 0)
        {
                //pid小于的时候,fork()系统调用出错,
                printf("fork() create child process failure:%s\n",strerror(errno));
                return -1;
        }
        else if(pid == 0)
        {
                //pid等于0的时候,子进程开始运行
                printf("child process start excute ifconfig program");

                //此时子进程重定向标准输出到父进程所打开的文件里面
                dup2(fd,STDOUT_FILENO);

                execl("/sbin/ifconfig","ifconfig","enp2s0",NULL);
                //子进程在上一条代码之后会去执行另一个程序,后面的代码不会再去执行,如果执行>了,表示出错了
                printf("child process excute another failure:%s\n",strerror(errno));
                return -1;
        }
        else
        {
                //当pid大于0的时候,父进程执行
                sleep(3);

                //子进程将另一个程序的输出到文件中去之后,文件的偏移量(光标)这会读不出文件>的内容
                lseek(fd,0,SEEK_SET);
                //将文件偏移量设置在最开始的地方

                rv = read(fd,buf,sizeof(buf));
                printf("read %d bytes data after lseek:%s \n",rv,buf);

        }
        close(fd);
        unlink(TMP_FILE1);
        return 0;

通过这个简单的例子可以实现在一个程序中去执行另一个程序,并可以对另一个程序的结果进行处理,由于只是作为例子,我并没有对另一个程序的结果进行什么处理,只是做了简单的输出。代码中注释较为详细,在此不多赘述。

二、system()函数

该函数使用起来就简单多了,代码如下:(就是说示例就一切从简了嗷)

#include <stdlib.h>
int main(int argc,char ** argv)
{
        system("ping -c 4 -I enp2s0 4.2.2.2");
        return 0;
}

其输出结果如下图所示:

在这里插入图片描述

三、popen()函数

该函数可以执行一条命令,并会返回一个基于管道(pipe)的文件流,然后可以从文件流中的一行进行解析了。

示例代码如下

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>

int get_ipaddr(char *interface,char *ipaddr,int ipaddr_size);
//函数声明 通过参数:接口、ip地址、ip地址长度获取ip地址


int main(int argc,char **argv)
{
        char    ipaddr[16];
        char    *interface = "enp2s0";

        memset(ipaddr,0,sizeof(ipaddr));

        if(get_ipaddr(interface,ipaddr,sizeof(ipaddr)) < 0)
        {
                printf("ERROR: get IP address failure\n");
                return -1;
        }
        return 0;
}

int get_ipaddr(char *interface,char *ipaddr,int ipaddr_size)
{
        char    buf[1024];
        FILE    *fp;
        int     len;
        int     rv;

        if( !interface || !ipaddr || ipaddr_size < 16)  //当接口 或者 地址 或者IP地址的长度错
误的时候,输出错误提示
        {
                printf("invalid input arguments\n");
                return -1;
        }

        memset(buf,0,sizeof(buf));
        snprintf(buf,sizeof(buf),"ifconfig %s",interface);
 if(NULL == (fp = popen(buf,"r")))
        {
                printf("popen() to excute command \"%s\" failure: %s\n",buf,strerror(errno));
                return -2;
        }

        rv = -3;
        //set default return value to -3 means parser failure


        while( fgets(buf,sizeof(buf),fp))
        {

                //fgets()函数其实就是一行一行的文件里面的内容
                printf("you can deal with you file in here\n");

                rv = 0;         //parser IP address ok and set rv to 0
                break;

        }
        return rv;

同样作为示例代码并没有对另一程序的输出内容做实际的处理。只给出了一些框架概念。避免文章没有重点过于冗长,要是有需要,后续可以再更新。


总结

该篇文章写了我目前知道的三种在程序中可以运行另一个程序的方法,下一篇正式开始写多进程的通信辣!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值