Linux进程之execl族函数、system函数

execl族函数

int execl(const char * path,const char * arg,…);

int execle(const char * path,const char * arg,char * const envp[]);

int execlp(const char * file,const char * arg,…);

int execv(const char * path,char * const argv[]);

int execve(const char * path,char * const argv[],char * const envp[]);

int execvp(const char * file,char * const argv[]);

        execl族函数除了execle()和execve()不常用以外,其他的都经常用。execl族函数的作用在于可以在进程或者代码中执行可执行文件,也就是以.exe结尾的文件。从而使执行的可执行文件变成一个新的进程。

#include <unistd.h>

        这是execl族的头文件。

path:要执行的程序路径。可以是绝对路径或者是相对路径。在execv、execve、execl和execle这4个函数中,使用带路径名的文件名作为参数。

file:要执行的程序名称。如果该参数中包含“/”字符,则视为路径名直接执行;否则视为单独的文件名,系统将根据PATH环境变量指定的路径顺序搜索指定的文件。

argv:命令行参数的矢量数组。

envp:带有该参数的exec函数可以在调用时指定一个环境变量数组。其他不带该参数的exec函数则使用调用进程的环境变量。

arg:程序的第0个参数,即程序名自身。相当于argv[0]。

#include <stdio.h>

int main()
{
        printf("hello world\n");

        return 0;
}

        先写一个最简单的代码,然后编译成可执行文件hello。

CLC@Embed_Learn:~/test_11.7$ gcc hello.c -o hello
CLC@Embed_Learn:~/test_11.7$ ls
a.out  hello  hello.c  test1.c 

        我们可以看到多了一个hello的可执行文件,这里看不出来,在linux系统下可执行文件会变成绿色。接下来使用一下exec()函数。 

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

int main()
{
        if(execl("./hello",NULL,NULL) == -1)
        {
                printf("error\n");
        }
        printf("ok\n");

        return 0;
}

        execl()函数我这里有3个参数,第一个参数是文件路径,哦这里写的是当前路径下hello这个可执行文件,后面两个都是NULL。其实execl()函数可以有很多参数,但是最后一个参数必须是NULL,中间的参数是execl()函数执行的可执行文件的参数。看一下效果。

CLC@Embed_Learn:~/test_11.7$ gcc test2.c
CLC@Embed_Learn:~/test_11.7$ ./a.out
hello world 

        我们发现,他也打印了一个hello world。因为hello这个可执行文件里面的代码就是打印一个hello world。

        之前说过,当execl()函数执行一个可执行文件之后,它就会变成一个新进程,我们也可以看到最后的一段打印ok的代码它并不会执行。如果执行失败会是什么效果?

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

int main()
{
        if(execl("./hello.c",NULL,NULL) == -1)
        {
                printf("error\n");
        }
        printf("ok\n");

        return 0;
}

        代码做了一点修改,把hello可执行文件改成了hello.c,但是我的目录下并不存在这个可执行文件,所有理论上会执行失败。

CLC@Embed_Learn:~/test_11.7$ gcc test2.c
CLC@Embed_Learn:~/test_11.7$ ./a.out
error
ok
CLC@Embed_Learn:~/test_11.7$  

        执行后,终端打印了error和ok,这就说明新的进程没有创建成功,代码会从头执行到尾,ok也被打印了出来。

        execl()函数我目前使用了3个参数,第一个是可执行文件的路径,第三个也就是最后一个必须是NULL ,那么中间的参数怎么使用呢?

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

int main()
{
        if(execl("/bin/ls","ls","-l",NULL) == -1)
        {
                printf("error\n");
        }
        printf("ok\n");

        return 0;
}

        我这里中间给了2个参数,一个是ls,一个是-l。我们可执行文件是linux系统的bin目录下面的ls可执行文件。在我们使用linux系统时,输入ls它会列出当前目录下的文件,如果再加上-l选项,它会把每个文件的详细信息列出来。

        我代码里的execl()函数演示的就是这个效果。可以对比一下。

CLC@Embed_Learn:~/test_11.7$ ls -l
total 40
-rwxr-xr-x 1 CLC book 8428 Nov  7 15:43 a.out
-rwxr-xr-x 1 CLC book 8377 Nov  7 14:50 hello
-rw-r--r-- 1 CLC book   74 Nov  7 14:49 hello.c
-rw-r--r-- 1 CLC book  363 Nov  7 14:52 test1.c
-rw-r--r-- 1 CLC book  172 Nov  7 15:38 test2.c
-rw-r--r-- 1 CLC book  175 Nov  7 15:49 test3.c
CLC@Embed_Learn:~/test_11.7$ gcc test3.c
CLC@Embed_Learn:~/test_11.7$ ./a.out
total 40
-rwxr-xr-x 1 CLC book 8428 Nov  7 15:49 a.out
-rwxr-xr-x 1 CLC book 8377 Nov  7 14:50 hello
-rw-r--r-- 1 CLC book   74 Nov  7 14:49 hello.c
-rw-r--r-- 1 CLC book  363 Nov  7 14:52 test1.c
-rw-r--r-- 1 CLC book  172 Nov  7 15:38 test2.c
-rw-r--r-- 1 CLC book  175 Nov  7 15:49 test3.c
CLC@Embed_Learn:~/test_11.7$ 

        可以看到,效果一模一样。接下来使用一下execlp()函数。

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

int main()
{
        if(execlp("ls","ls","-l",NULL) == -1)
        {
                printf("error\n");
        }
        printf("ok\n");

        return 0;
}

        代码做了一些小调整,execlp()函数对比execl()函数来说,它的好处就是可以在整个linux系统中搜索你这个可执行文件,不需要加上目录,我们可以看看效果。

CLC@Embed_Learn:~/test_11.7$ gcc test4.c
CLC@Embed_Learn:~/test_11.7$ ./a.out
total 44
-rwxr-xr-x 1 CLC book 8429 Nov  7 15:54 a.out
-rwxr-xr-x 1 CLC book 8377 Nov  7 14:50 hello
-rw-r--r-- 1 CLC book   74 Nov  7 14:49 hello.c
-rw-r--r-- 1 CLC book  363 Nov  7 14:52 test1.c
-rw-r--r-- 1 CLC book  172 Nov  7 15:38 test2.c
-rw-r--r-- 1 CLC book  175 Nov  7 15:49 test3.c
-rw-r--r-- 1 CLC book  171 Nov  7 15:54 test4.c
CLC@Embed_Learn:~/test_11.7$  

        没什么区别。其他的族函数就不过多介绍了。 

system函数

#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <unistd.h>

int system(const char * cmdstring)
{
    pid_t pid;
    int status;

    if(cmdstring == NULL){
           
         return (1);
    }

    if((pid = fork())<0){

            status = -1;
    }else if(pid = 0){

        execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);

        -exit(127); //子进程正常执行则不会执行此语句

    }else{
            while(waitpid(pid, &status, 0) < 0){

                if(errno != EINTER){

                    status = -1;

                    break;

                }
            }
        }
        return status;
}

        上面这段代码是system()函数的源码,首先创建一个子进程,然后调用execl()函数来创建一个新进程取执行可执行文件。 

        我们可以看到execl()函数有5个参数,第五个参数(char*)0其实就是NULL的意思。第一个参数是可执行文件的目录,是linux系统bin目录下的sh可执行文件。第二和第三个参数分别是sh和-c,同时也是sh这个可执行文件的参数。

        举个例子,平时我们编写代码先是用gcc命令把代码编译成可执行文件,然后再用./a.out来运行。这是我们通常的用法,但是你用sh -c指令也可以运行。

CLC@Embed_Learn:~/test_11.7$ gcc hello.c -o hello
CLC@Embed_Learn:~/test_11.7$ ./hello
hello world
CLC@Embed_Learn:~/test_11.7$ sh -c ./hello
hello world

        接下来我们再带入这个execl()函数。

execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);

        第二和第三个参数就相当于你在终端输入sh -c这个指令,cmdstring是system()函数的参数。sh -c ./hello这段命令就相当于system("./hello"),举个例子。

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

int main()
{
        if(system("./hello") == -1)
        {
                printf("error\n");
        }

        return 0;
}

CLC@Embed_Learn:~/test_11.7$ gcc test5.c
CLC@Embed_Learn:~/test_11.7$ ./a.out 
hello world
CLC@Embed_Learn:~/test_11.7$  

        效果都是一样的,简单点来说,system()函数的底层就是execl()函数。 

 

 

         

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

六花不会哭T﹏T

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值