linux进程
命令行参数
C程序的main函数原型
int main(int argc, char *argv[]);
参数
操作系统将命令行参数传递给main函数
- argc,命令行参数的个数
- argv,命令行参数数组
例子
cp /etc/passwd passwd.bak
argc = 3
argv = {"cp", "/etc/passwd", "passwd.bak"}
命令名也被当作是命令参数,所以argc != 2
execl
原型
#include <unistd.h>
int execl(const char *path, const char *arg, ...);
功能
- 将当前进程的地址空间的内容全部清空
- 将path指定的可执行程序的代码和数据装入到当前进程的地址空间
参数 - 该函数的参数个数可变
- 最后一个参数必须是NULL
- 第一个参数path指定被装入程序的路径
- 可以是命令的绝对路径
- 可以是命令的相对路径
返回值
- 装入失败后,返回值为-1
- 装入成功后,从被装入程序的main函数开始执行
execlp
原型
#include <unistd.h>
int execlp(const char *file, const char *arg, ...);
功能
与execl相同
execl和execlp的区别
在execl中,第一个参数指定可执行程序的路径
该路径可以是
- 绝对路径
- 相对于当前工作目录的相对路径
在execlp中,第一个参数指定可执行程序的路径
该路径可以是 - 绝对路径
- 相对于当前工作目录的相对路径
- PATH环境变量指定目录下的相对路径
例子
#include <stdio.h>
#include <unistd.h>
int main()
{
puts("before exec");
int error = execlp("echo", "echo", "a", "b", "c", NULL);
if (error < 0)
perror("execl");
puts("after exec");
return 0;
}
output:
$ cc execlp.c
$ ./a.out
before exec
a b c
$ _
execv
原型
#include <unistd.h>
int execv(const char *path, const char *argv[]);
功能
与execl相同
参数
- argv指定传递给程序的参数,argv数组的最后一项必须是NULL指针
execl和execv的区别
execl,函数名execl末尾的l表示list,参数以列表的形式传递给可执行程序
execl("/bin/echo", "echo", "a", "b", "c", NULL);
execv,函数名execv末尾的v表示vector,参数以数组的形式传递给可执行程序
char *argv[] = {"echo", "a", "b", "c", NULL};
execv("/bin/echo", argv);
execvp
同上
例子
#include <stdio.h>
#include <unistd.h>
int main()
{
puts("before exec");
char *argv[] = {"echo", "a", "b", "c", NULL};
int error = execvp("echo", argv);
if (error < 0)
perror("execv");
puts("after exec");
return 0;
}
exit
原型
#include <stdlib.h>
void exit(int status);
功能
- 正常退出当前进程
将status & 0xFF作为退出码返回给父进程 - 预定义常量
EXIT_SUCCESS,为0的数值,表示程序正常退出
EXIT_FAILURE,为非0的数值,表示程序执行过程发生了错误,异常退出 - 在linux shell中,可以通过特殊的环境变量$?获得程序的退出码
atexit
原型
#include <stdlib.h>
int atexit(void (*function)(void));
功能
- 注册一个回调函数function,进程正常结束时,function会被调用
如果注册多个回调函数,进程结束时,以与注册相反的顺序调用回调函数
例子
#include <stdio.h>
#include <stdlib.h>
void f1()
{
puts("f1");
}
void f2()
{
puts("f2");
}
void f3()
{
puts("f3");
}
int main()
{
atexit(f1);
atexit(f2);
atexit(f3);
puts("main");
return 0;
}
输出:
$ cc atexit.c
$ ./a.out
main
f3
f2
f1
$ _
wait
原型
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
功能
- 等待子进程结束
参数
- status,如果status不为NULL,子进程的退出码保存在status指向的变量中
退出码
- 进程可能由于不同的原因退出
- 主动调用exit正常退出
- 接受信号后退出
- 查询退出原因的宏
名称 | 功能 |
---|---|
WIFEXITED(status) | 如果进程通过调用exit正常退出,则返回真 |
WEXITSTATUS(status) | 如果进程通过调用exit正常退出,返回进程的退出码 |
WIFSIGNALED(status) | 如果进程接受信号后退出,则返回真 |
WTERMSIG(status) | 如果进程接受信号后退出,返回导致进程退出的信号 |
例子
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
void child()
{
exit(123);
}
int main()
{
int pid;
pid = fork();
if (pid == 0)
child();
int status;
wait(&status);
if (WIFEXITED(status)) {
printf("WIFEXITED = true\n");
printf("WEXITSTATUS = %d\n", WEXITSTATUS(status));
}
return 0;
}
- 父进程调用wait,等待子进程结束
- 将变量status的地址传递给wait
- 用于接受子进程的退出码
$ cc wait2.c
$ ./a.out
WIFEXITED = true
WEXITSTATUS = 123
$ _