C 语言 系统调用 system()、exec() 函数的使用
系统调用就是操作系统内核函数, 通过 stdlib.h
库,为 C 提供很多接口。
1.1 system() 函数
system("dir D:"); // windows:打印 D 盘内容 system("gedit"); // *unix:启动编辑器 system("say 'you are SB'"); //mac:朗读文本
system()
函数在操作系统上,当调用它时操作系统必须解释命令字符串,然后决定运行哪些程序和怎么运行,但存在很大安全问题, 如删除一些东西,注入恶意代码,更改环境变量等, 要解决这个问题就必须消除歧义,明确告诉操作系统运行什么程序,而不是由操作系统瞎解释。在 C 中用 exec()
函数来告知。
1.2 exec() 函数替换当前进程
进程是存储器中运行的程序,如输入 ps -ef
则看到一堆输出,操作系统用一个数字来标识进程,叫进程标识符(process identifier 简称 PID)。
exec() 装入并运行其它程序的函数,把进程交接给了新程序。
1.3 exec() 函数有很多
版本众多,分列表函数和数组函数
1.3.1 列表函数:execl()、execlp()、execle()
列表函数以参数列表的形式接收命令行参数:
1.3.2 数组函数:execv(), execvp(), execve()
1.3.3 实例
execl()
:
/* 函数说明:execl() 用来执行参数 path 字符串所代表的文件路径, 接下来的参数代表执行该文件时传递过去的 argv(0), argv[1], ..., 最后一个参数必须用空指针(NULL) 作结束. */ #include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) { execl("/bin/ls", "ls", "-al", "/etc/passwd", NULL); return 0; }
execlp()
:
/* 同 execlp,第一个参数不是路径而是通过环境变量的命令 */ #include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) { execlp("ls", "ls", "-al", ".", NULL); // command: ls return 0; }
execv()
:
/* execv: 接收两个参数, path 和 字符串数组指针 */ #include <stdio.h> #include <unistd.h> int main() { char *args[] = {"ls", "-al", "/etc/passwd", NULL}; execv("/bin/ls", args); return 0; }
execve()
:
/* 函数说明:execve() 用来执行参数 filename 字符串所代表的文件路径, 第二个参数系利用数组指针来传递给执行文件, 最后一个参数则为传递给执行文件的新环境变量数组. */ #include <stdio.h> #include <unistd.h> int main(){ char *argv[] = {"ls", "-al", "/etc/passwd", NULL}; char *env[] = {"PATH=/bin", 0}; execve("/bin/ls", argv, env); return 0; }
execvp()
:
/* *函数说明:execvp() 会从 PATH 环境变量所指的目录中查找符合参数 file 的文件名, 找到后便执行该文件, 然后将第二个参数 argv 传给该欲执行的文件。 */ #include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]){ char *args[] = {"ls", "-al", "/etc/passwd", 0}; execvp("ls", args); return 0; }
1.3.4 传递环境变量
每个进程都有一组环境变量, 命令行中使用 set
或 env
查看它们的值。C 用 getenv()
系统调用读取环境变量.如果想用命令行参数和环境变量运行程序,可以这样做:
// diner_info.c #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]){ printf("%s\n", argv[1]); printf("%s\n", getenv("JUICE")); return 0; } // main.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[]) { char *my_env[] = {"JUICE=peach and apple", NULL}; // 字符串指针数组创建一组环境变量 execle("diner_info", "diner_info", "4", NULL, my_env); return 0; }
main.c 用来通过参数列表和环境变量字符数组来调用 diner_info 可执行文件:
execle() 函数将设置命令行参数和环境变量,然后用 diner_info 替换当前进程。
gcc diner_info.c -o diner_info gcc main.c -o main ./main 4 peach and apple
1.4 系统调用失败的处理法则
一旦系统调用如 exec()
失败则就不会继续往下走了,处理失败的黄金法则摘抄如下:
- 尽可能收拾残局
- 把 errno 变量设为错误码
- 返回-1
errno
变量是定义在 errno.h
中的全
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: C 语言 可变参数函数
下一篇: 彻底找到 Tomcat 启动速度慢的元凶
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论