完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
exec函数族
1)exec函数族说明 fork()函数用于创建一个子进程,该子进程几乎复制了父进程的全部内容,但是,这个新创建的进程如何执行呢?exec函数族就提供了一个在进程中启动另一个程序执行的方法。它可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程号外,其他全部被新的进程替换了。另外,这里的可执行文件既可以是二进制文件,也可以是Linux下任何可执行的脚本文件。 在Linux中使用exec函数族主要有两种情况: ● 当进程认为自己不能再为系统和用户做出任何贡献时,就可以调用exec函数族中的任意一个函数让自己重生。 ● 如果一个进程想执行另一个程序,那么它就可以调用fork()函数新建一个进程,然后调用exec函数族中的任意一个函数,这样看起来就像通过执行应用程序而产生了一个新进程(这种情况非常普遍)。 2)exec函数族语法 实际上,在Linux中并没有exec()函数,而是有6个以exec开头的函数,它们之间的语法有细微差别,本书在后面会详细讲解。 表2列举了exec函数族的6个成员函数的语法。 表2 exec函数族成员函数语法
● 查找方式。读者可以注意到,表2中的前4个函数的查找方式都是完整的文件目录路径,而最后两个函数(也就是以p结尾的两个函数)可以只给出文件名,系统就会自动按照环境变量“$PATH”所指定的路径进行查找。 ● 参数传递方式。exec函数族的参数传递有两种方式:一种是逐个列举的方式,而另一种则是将所有参数整体构造指针数组传递。在这里是以函数名的第5位字母来区分的,字母为“l”(list)的表示逐个列举参数的方式,其语法为const char *arg;字母为“v”(vertor)的表示将所有参数整体构造指针数组传递,其语法为char *const argv[]。读者可以观察execl()、execle()、execlp()的语法与execv()、execve()、execvp()的区别,它们的具体用法在后面的实例讲解中会具体说明。 这里的参数实际上就是用户在使用这个可执行文件时所需的全部命令选项字符串(包括该可执行程序命令本身)。要注意的是,这些参数必须以NULL结束。 ● 环境变量。exec函数族可以默认系统的环境变量,也可以传入指定的环境变量。这里以“e”(environment)结尾的两个函数execle()和execve()就可以在envp[]中指定当前进程所使用的环境变量。 表3再对这6个函数中的函数名和对应语法做了一个小结,主要指出了函数名中每一位所表明的含义,希望读者结合此表加以记忆。 表3 exec函数名对应含义
● 找不到文件或路径,此时errno被设置为ENOENT。 ● 数组argv和envp忘记用NULL结束,此时errno被设置为EFAUL。 ● 没有对应可执行文件的运行权限,此时errno被设置为EACCES。 3)exec使用实例 下面的第一个示例说明了如何使用文件名的方式来查找可执行文件,同时使用参数列表的方式。这里用的函数是execlp()。 /* execlp.c */ 在该程序中,首先使用fork()函数创建一个子进程,然后在子进程中使用execlp()函数。读者可以看到,这里的参数列表列出了在shell中使用的命令名和选项,并且当使用文件名进行查找时,系统会在默认的环境变量PATH中寻找该可执行文件。读者可将编译后的结果下载到目标板上,运行结果如下:#include #include #include int main() { if (fork() == 0) { /* 调用execlp()函数,这里相当于调用了“ps –ef”命令 */ if ((ret = execlp("ps", "ps", "-ef", NULL)) < 0) { printf("Execlp errorn"); } } } $ ./execlp 此程序的运行结果与在shell中直接输入命令“ps -ef”是一样的,当然,在不同系统的不同时刻可能会有不同的结果。PID TTY Uid Size State Command 1 root 1832 S init 2 root 0 S [keventd] 3 root 0 S [ksoftirqd_CPU0] 4 root 0 S [kswapd] 5 root 0 S [bdflush] 6 root 0 S [kupdated] 7 root 0 S [mtdblockd] 8 root 0 S [khubd] 35 root 2104 S /bin/bash /usr/etc/rc.local 36 root 2324 S /bin/bash 41 root 1364 S /***in/inetd 53 root 14260 S /Qtopia/qtopia-free-1.7.0/bin/qpe -qws 54 root 11672 S quicklauncher 65 root 0 S [u***-storage-0] 66 root 0 S [scsi_eh_0] 83 root 2020 R ps -ef $ env … PATH=/Qtopia/qtopia-free-1.7.0/bin:/usr/bin:/bin:/usr/***in:/***in … 接下来的示例使用完整的文件目录来查找对应的可执行文件。注意,目录必须以“/”开头,否则将其视为文件名。 /* execl.c */ 同样将代码下载到目标板上运行,运行结果同上例。#include #include #include int main() { if (fork() == 0) { /* 调用execl()函数,注意这里要给出ps程序所在的完整路径 */ if (execl("/bin/ps","ps","-ef",NULL) < 0) { printf("Execl errorn"); } } } 下面的示例利用execle()函数将环境变量添加到新建的子进程中,这里的“env”是查看当前进程环境变量的命令,代码如下: /* execle.c */ 下载到目标板后的运行结果如下:#include #include #include int main() { /* 命令参数列表,必须以NULL结尾 */ char *envp[]={"PATH=/tmp","USER=david", NULL}; if (fork() == 0) { /* 调用execle()函数,注意这里也要指出env的完整路径 */ if (execle("/usr/bin/env", "env", NULL, envp) < 0) { printf("Execle errorn"); } } } $ ./execle 最后一个示例使用execve()函数,通过构造指针数组的方式来传递参数,注意参数列表一定要以NULL作为结尾标识符。其代码如下:PATH=/tmp USER=sunq #include 下载到目标板后的运行结果如下:#include #include int main() { /* 命令参数列表,必须以NULL结尾 */ char *arg[] = {"env", NULL}; char *envp[] = {"PATH=/tmp", "USER=david", NULL}; if (fork() == 0) { if (execve("/usr/bin/env", arg, envp) < 0) { printf("Execve errorn"); } } } $ ./execve PATH=/tmp USER=david |
||
相关推荐
|
||
void fun(){
printf(“Hello, My name is zhangsan.”); } |
|
|
|
|
|
只有小组成员才能发言,加入小组>>
「含关键代码」基于AM3352/AM3354/AM3359的Linux开发案例分享
4870 浏览 0 评论
87363 浏览 0 评论
【高手问答】如何做到精通linux技术?资深工程师带你突破难点
4681 浏览 2 评论
3568 浏览 2 评论
解读Linux :先从创建一个文件夹用来存放jdk压缩文件开始
2456 浏览 0 评论
1952浏览 3评论
这是i.mx6ull的关于usb的宏定义,能解释下这些宏定义的意思
1321浏览 1评论
1231浏览 1评论
求解:aarch64交叉编译工具已经安装成功,环境变量已经配置,怎么将系统架构切换为ARM的架构
1296浏览 0评论
电脑和虚拟机可以互ping,电脑和开发板也可以互ping,但是虚拟机和开发板ping不通是什么原因
1214浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-25 20:14 , Processed in 0.916511 second(s), Total 44, Slave 36 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号