qt调用linux系统调用,Linux 系统调用 exec

exec

exec 函数族的作用是执行参数所指定的可执行文件或脚本。这个函数会替换掉当前进

程的内存镜像,也就是执行这个函数成功后,调用该函数的程序就不存在了,像是移

花接木一样。Linux下的的 exec 并不是一个函数,而是一族函数,一共有如下几个函

数,原型为:

1

2

3

4

5

6

7

8

9

10

11

12

13int execve(const char *filename, char *const argv[],

char *const envp[]);

int execl(const char *path, const char *arg, ...

/* (char *) NULL */);

int execlp(const char *file, const char *arg, ...

/* (char *) NULL */);

int execle(const char *path, const char *arg, ...

/*, (char *) NULL, 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[]);

这 7 个函数中只有execve()是真正的系统调用函数,其它几个最终都会调用它。

exec 后面的字母的含义为:

字母

助记

含义

l

list

参数逐个列举

v

vector

用向量(字符串数组)传递参数

p

path (I guess~)

从$PATH中查找可执行文件

e

environment

设置环境变量

Special semantics for execlp() and execvp()

The execlp(), execvp(), and execvpe() functions duplicate the actions of

the shell in searching for an executable file if the specified filename

does not contain a slash (/) character. The file is sought in the

colon-separated list of directory pathnames specified in the PATH

environment variable. If this variable isn’t defined, the path list

defaults to the current directory followed by the list of directories

returned by confstr(_CS_PATH). (This confstr(3) call typically returns

the value “/bin:/usr/bin”.)

意思是:如果指定的文件名不包含/的话,execlp()`execvp()execvpe()会重

复 shell 查找可执行文件的行为(即从环境变量PATH所指定的目录中寻找文件)。

如果变量PATH没有设置,会使用当前目录加上confstr(_CS_PATH, …)`的输出作

为目录集并从中寻找可执行文件。

当目录里没有/且没有设置PATH时,man exec中说会将当前目录加入查找可执行

文件的目录集,但我测试似乎并没有当前目录,也可能是我理解错了。测试代码如下:

1

2

3

4

5

6

7

8

9

10

11

12#include

#include

#include

int main(int argc, char *argv[])

{

if (execlp("argv", 0)) {

perror("execlp failed");

exit(1);

}

return 0;

}

命令如下:

1

2

3

4

5

6$ clang execlp.c -o execlp

$ ./execlp

execlp failed: No such file or directory

$ unset PATH

$ ./execlp

execlp failed: No such file or directory

全都提示找不到文件。以下是一些例子。

例子 1

先写一个辅助程序,打印出程序执行的一些信息(argv 和 envp):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31/*

* argv.c

* $ clang argv.c -o argv

*/

#include

int main(int argc, char *argv[], char *envp[])

{

extern char **environ;

int i;

printf("pid: %d\n", getpid());

/* print argv */

printf("%s\n", "argv");

for (i=0; i < argc; i++) {

printf(" argv[%d]: %s\n", i, argv[i]);

}

/* print envp */

printf("%s\n", "envp(0~4)");

for (i=0; envp[i] && i != 5; i++) {

printf(" envp[%d]: %s\n", i, envp[i]);

}

/* print environ, should be the same with envp */

printf("%s\n", "environ(0~4)");

for (i=0; environ[i] && i != 5; i++) {

printf(" environ[%d]: %s\n", i, environ[i]);

}

return 0;

}

由于环境变量太多,这时只打印出前 5 个。下面是execve()的一个例子:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28/* execve.c */

#include

#include

#include

#include

int main(int argc, char *argv[], char *envp[])

{

char *const pg_argv[] = {"./argv", "-dummy-param", NULL};

char *pg_envp[] = {"some_key_val_pair", NULL};

printf("0 -----------------------------\n");

if (fork()) {

wait(0);

} else {

if (execve("./argv", pg_argv, envp) == -1)

perror("execve error: ");

}

printf("1 -----------------------------\n");

if (fork()) {

wait(0);

} else {

if (execve("./argv", pg_argv, pg_envp) == -1)

perror("execve error: ");

}

return 0;

}

execve()执行成功是不会返回的,只有在失败的时候会返回-1,并设置相应的

errno。在我电脑上的执行结果为:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30$ clang argv.c -o argv

$ clang execve.c -o execve

$ ./execve

pid of parent: 11900

0 -----------------------------

pid: 11901

argv

argv[0]: ./argv

argv[1]: -dummy-param

envp(0~4)

envp[0]: XAUTHORITY=/tmp/xauth-1000-_0

envp[1]: LC_PAPER=en_US.UTF-8

envp[2]: QT_ACCESSIBILITY=1

envp[3]: LC_MEASUREMENT=en_US.UTF-8

envp[4]: PAM_KWALLET_LOGIN=/tmp/kwallet_qi.socket

environ(0~4)

environ[0]: XAUTHORITY=/tmp/xauth-1000-_0

environ[1]: LC_PAPER=en_US.UTF-8

environ[2]: QT_ACCESSIBILITY=1

environ[3]: LC_MEASUREMENT=en_US.UTF-8

environ[4]: PAM_KWALLET_LOGIN=/tmp/kwallet_qi.socket

1 -----------------------------

pid: 11902

argv

argv[0]: ./argv

argv[1]: -dummy-param

envp(0~4)

envp[0]: some_key_val_pair

environ(0~4)

environ[0]: some_key_val_pair

例子 2

还有一个例子:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19/* execve_pid.c */

#include

#include

#include

int main(int argc, char *argv[], char *envp[])

{

char *const pg_argv[] = {"./argv", "-dummy-param", NULL};

char *pg_envp[] = {"some_key_val_pair", NULL};

printf("pid: %d\n", getpid());

printf("---------- before execve -----------\n");

if (execve("./argv", pg_argv, pg_envp) == -1)

perror("execve error: ");

return 0;

}

执行结果为:

1

2

3

4

5

6

7

8

9

10

11

12$ clang execve_pid.c -o execve_pid

$ ./execve_pid

pid: 11956

---------- before execve -----------

pid: 11956

argv

argv[0]: ./argv

argv[1]: -dummy-param

envp(0~4)

envp[0]: some_key_val_pair

environ(0~4)

environ[0]: some_key_val_pair

可以看到执行了execve()后进程 ID 没有变化,可知原进程被替换了。而且在指定

了envp参数时,进程不再继承 shell 的环境变量。

ReferencesLinux 手册:man exec,man execve,man confstr

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值