C 语言 系统调用 system()、exec() 函数的使用

发布于 2024-06-28 00:07:31 字数 4207 浏览 23 评论 0

系统调用就是操作系统内核函数, 通过 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 传递环境变量

每个进程都有一组环境变量, 命令行中使用 setenv 查看它们的值。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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

谢绝鈎搭

暂无简介

0 文章
0 评论
897 人气
更多

推荐作者

13886483628

文章 0 评论 0

流年已逝

文章 0 评论 0

℡寂寞咖啡

文章 0 评论 0

笑看君怀她人

文章 0 评论 0

wkeithbarry

文章 0 评论 0

素手挽清风

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文