前言
有时候在写代码的时候我们会需要一个程序的执行结果,这个时候我们可以通过本文的三种方法,使用子进程来运行该程序,并把运行结果重定向到文件(或者不需要这一步),然后就能某一个程序的运行结果,并在该代码中进行处理了。
提示:以下是本篇文章正文内容,下面案例可供参考
一、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;
同样作为示例代码并没有对另一程序的输出内容做实际的处理。只给出了一些框架概念。避免文章没有重点过于冗长,要是有需要,后续可以再更新。
总结
该篇文章写了我目前知道的三种在程序中可以运行另一个程序的方法,下一篇正式开始写多进程的通信辣!!!