linux系统编程---exec族函数、system函数、popen函数

一、exec族函数

exec族函数函数的作用:

我们用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时,该进程被完全替换为新程序。因为调用exec函数并不创建新进程,所以前后进程的ID并没有改变。

exec族函数定义:

功能:
  在调用进程内部执行一个可执行文件。可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。
函数族:
  exec函数族分别是:execl, execlp, execle, execv, execvp, execvpe
函数原型:

#include 
extern char **environ;

int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);

返回值:
  exec函数族的函数执行成功后不会返回,调用失败时,会设置errno并返回-1,然后从原程序的调用点接着往下执行。
参数说明:
path:可执行文件的路径名字
arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径且arg必须以NULL结束
file:如果参数file中包含/,则就将其视为路径名,否则就按 PATH环境变量,在它所指定的各目录中搜寻可执行文件。

exec族函数参数极难记忆和分辨,函数名中的字符会给我们一些帮助:
l : 使用参数列表
p:使用文件名,并从PATH环境进行寻找可执行文件
v:应先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数。
e:多了envp[]数组,使用新的环境变量代替调用进程的环境变量

(1)execl函数用法

文件echoarg.c

#include 
int main(int argc,char *argv[])
{
int i;
for(i=0;i<argc;i++)
{
printf("argv[%d]:%s\n",i,argv[i]);
}

return 0;
}

文件 a.c


#include 
#include 
#include 
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");
    //如果execl执行成功,下列代码就不会执行
    if(execl("./bin/echoarg","echoarg","abc",NULL) == -1)   //如果excel等于-1,执行失败,下面的代码就执行 
    {
        printf("execl failed!\n");     
        perror("Why"); 	//打印错误 
    }
    printf("after execl\n");  //execl执行成功则不打印这句话
    return 0;
}

运行结果:在当前目录下找不到文件的位置
linux系统编程---exec族函数、system函数、popen函数_第1张图片
文件b.c 与a.c的区别:

#include 
#include 
#include 
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");
    //如果execl执行成功,下列代码就不会执行
    if(execl("./echoarg","echoarg","abc",NULL) == -1)   //如果excel等于-1,执行失败,下面的代码就执行 
    {
        printf("execl failed!\n");     
        perror("Why"); 	//打印错误 
    }
    printf("after execl\n");  //execl执行成功则不打印这句话
    return 0;
}

结果:
linux系统编程---exec族函数、system函数、popen函数_第2张图片
调用成功了

(2)execlp函数解析:

如果参数file中包含/,则就将其视为路径名,否则就按 PATH环境变量,在它所指定的各目录中搜寻可执行文件。举个例子,PATH=/bin:/usr/bin

#include 
#include 
#include 
//函数原型:int execlp(const char *file, const char *arg, ...);

int main(void)
{
    printf("before execl\n");
    //如果execlp执行成功,下列代码就不会执行
    if(execlp("ps","ps",NULL,NULL) == -1)   //如果excel等于-1,执行失败,下面的代码就执行 
    {
        printf("execl failed!\n");     
        perror("Why"); 	//打印错误 
    }
    printf("after execl\n");  //execl执行成功则不打印这句话
    return 0;
}

结果:
linux系统编程---exec族函数、system函数、popen函数_第3张图片
总结:从上面的实验结果可以看出,上面的exaclp函数带p,所以能通过环境变量PATH查找到可执行文件ps

(3)execv函数的用法

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 
  5 int main(void)
  6 {
  7          printf("before execl\n");
  8          
  9         char *argv[] = {"ps",NULL,NULL};
 10         if(execv("/bin/ps",argv) == -1)  //需要添加路径来找到执行文件
 11          {
 12                 printf("execl failed!\n");
 13                 
 14                 perror("Why failed");
 15                 
 16         }
 17         
 18         printf("after execl\n");
 19         
 20         return 0;
 21 } 

结果:
linux系统编程---exec族函数、system函数、popen函数_第4张图片

二、system函数

linux系统编程---exec族函数、system函数、popen函数_第5张图片
文件changnew:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
	pid_t pid;
	int data=10;
	while(1){
		printf("plase int data\n");
		scanf("%d",&data);

		if(data==1){              
			int fdSrc;
			pid= fork();
			if(pid>0){
				wait(NULL);

			}

			if(pid==0){

				char *readbuf=NULL;

				fdSrc= open("TEST.config",O_RDWR);


				int size=  lseek(fdSrc,0,SEEK_END);
				lseek(fdSrc,0,SEEK_SET);
				readbuf=(char *)malloc(sizeof(char)*size+8);

				int n_read=read(fdSrc,readbuf,size);

				char *p=  strstr(readbuf,"RNG=");
				if(p==NULL){
					printf("jieshu\n");
					exit(-1);
				}

				p=p+strlen("RNG=");
				*p= '5';
				lseek(fdSrc,0,SEEK_SET);
				int n_write =  write(fdSrc,readbuf,strlen(readbuf));
				close(fdSrc);
				exit(0);
			}
		}else {

			printf("wait do nothing\n");

		} 

	}         

	return 0;

}

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
        pid_t pid;
        int data=10;
        while(1){
                printf("plase int data\n");
                scanf("%d",&data);

                if(data==1){
                        int fdSrc;
                        pid= fork();
                        if(pid>0){
                                wait(NULL);
                        }
                        if(pid==0){

               //execl("./changnew","changnew","TEST.config",NULL);
                                system("./changnew TEST.config");  
                        }                
                }else {              

                        printf("wait do nothing\n");

                }                

        }      

        return 0;

}   

结果如下:
linux系统编程---exec族函数、system函数、popen函数_第6张图片

三、popen函数用法

linux系统编程---exec族函数、system函数、popen函数_第7张图片
参数说明:
popen()会调用fork()产生子进程,然后从子进程中调用/bin/sh -c来执行参数command的指令。
参数type可使用“r”代表读取,“w”代表写入。依照此type值,popen()会建立管道连到子进程的标准输出设备或标准输入设备,然后返回一个文件指针。随后进程便可利用此文件指针来读取子进程的输出设备或是写入到子进程的标准输入设备中。
如果 type 为 r,那么调用进程读进 command 的标准输出。
如果 type 为 w,那么调用进程写到 command 的标准输入。
返回值: 若成功则返回文件指针,否则返回NULL,错误原因存于errno中
代码示例:

#include 
#include 
#include 

int main()
{

    char ret[1024]={0};
      FILE *fp;
   fp=popen("ps","r");
  int nread=fread(ret,1,1024,fp);

  printf("read ret:%d,ret=%s\n",nread,ret);

     return 0;


}

结果如下:
在这里插入图片描述
结论:popen和system相比,popen可以将指令输出的结果打印出来,而system却不能。

你可能感兴趣的:(Linux系统编程)