共计 5046 个字符,预计需要花费 13 分钟才能阅读完成。
过程空间概要剖析
问题
execve(...)
的参数别离是什么?有什么意义?
int create_process(char *path, char *args[]) | |
{int ret = fork(); | |
if (ret == 0) {execve(path, args, NULL); | |
} | |
return ret; | |
} |
- execve 的实质是零碎调用而非函数!!
main 函数(默认过程入口)
int main(int argc, char *argv[])
agrc - 命令行参数个数 | |
argv - 命令行参数数组 |
留神:启动参数和环境变量【拷贝】于父过程
过程空间概要
过程参数存储剖析
mem.c
#include <stdio.h> | |
#include <stdlib.h> | |
static int g_init = 255; | |
static float g_uninit; | |
static void text() | |
{ | |
} | |
int main(int argc, char *argv[]) | |
{ | |
static double s_init = 0.255; | |
static double s_uninit; | |
int i = 0; | |
int *p = malloc(4); | |
printf("argv[0] = %p\n", argv[0]); | |
printf("&i = %p\n", &i); | |
printf("p = %p\n", p); | |
printf("&g_uninit = %p\n", &g_uninit); | |
printf("&s_uninit = %p\n", &s_uninit); | |
printf("&g_init = %p\n", &g_init); | |
printf("&s_init = %p\n", &s_init); | |
printf("text = %p\n", text); | |
free(p); | |
return 0; | |
} |
tiansong@tiansong:~/Desktop/linux$ ./mem.out | |
argv[0] = 0x7fff7e27210c | |
&i = 0x7fff7e270c0c | |
p = 0x55c17314d2a0 | |
&g_uninit = 0x55c1717eb028 | |
&s_uninit = 0x55c1717eb030 | |
&g_init = 0x55c1717eb010 | |
&s_init = 0x55c1717eb018 | |
text = 0x55c1717e81a9 |
上面程序输入什么?为什么?
child.c
#include <stdio.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
int main(int argc, char *argv[]) | |
{ | |
int i = 0; | |
sleep(3); | |
for (i=0; i<argc; ++i) {printf("exec = %d %s\n", getpid(), argv[i]); | |
} | |
return 0; | |
} |
parent.c
#include <stdio.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
#define EXE "helloword.out" | |
int create_process(char *path, char *args[]) | |
{int ret = fork(); | |
if (ret == 0) {execve(path, args, NULL); | |
} | |
return ret; | |
} | |
void zero_str(char *s) | |
{while (s && *s) *s++ = 0; | |
} | |
int main() | |
{char path[] = EXE; | |
char arg1[] = "hello"; | |
char arg2[] = "world"; | |
char *args[] = {path, arg1, arg2, NULL}; | |
printf("%d begin\n", getpid()); | |
printf("%d child = %d\n", getpid(), create_process(EXE, args)); | |
zero_str(path); | |
zero_str(arg1); | |
zero_str(arg2); | |
printf("%d path = %s\n", getpid(), path); | |
printf("%d arg1 = %s\n", getpid(), arg1); | |
printf("%d arg2 = %s\n", getpid(), arg2); | |
printf("%d end\n", getpid()); | |
return 0; | |
} |
tiansong@tiansong:~/Desktop/linux$ gcc parent.c -o parent.out | |
tiansong@tiansong:~/Desktop/linux$ gcc child.c -o helloword.out | |
tiansong@tiansong:~/Desktop/linux$ ./parent.out | |
4665 begin | |
4665 child = 4666 | |
4665 path = | |
4665 arg1 = | |
4665 arg2 = | |
4665 end | |
tiansong@tiansong:~/Desktop/linux$ exec = 4666 helloword.out | |
exec = 4666 hello | |
exec = 4666 world |
- 命令行参数,启动参数,过程参数实质雷同
命令行参数标准
Linux 启动参数(命令行参数)标准
- 由选项,选项值,操作数组成
- 选项由短横线 (-) 开始,选项名必须是单个字母或数字字符
- 选项能够有选项值,选项与选项值之间可用空格分隔(
-o test ←→ -otest
)[举荐前者] - 如果多个选项均无选项值,可合而为一 (
-a-b-c ←→ -abc
) [举荐前者] - 既不是选项,也不能作为选项值的参数是操作数
- 第一次呈现的双横线 (–) 用于完结所有选项,后续参数为操作数
gcc test.c -o test.out | |
操作数 选项 选项值 |
Linux 启动参数(命令行参数)解析
- 规定 :
if:s
(-i,-s,-f 选项值) - 示例:
Linux 启动参数(命令行参数)编程
#include <unistd.h> | |
extern char *optarg; | |
extern int optind, opterr, optopt; | |
int getopt(int argc, char *argv[], const char *optstring); |
getopt(...)
从 argv[] 数组中获取启动参数,并依据 optstring 定义的规定进行解析-
getopt(...)
从 argc 和 argv 中获取下一个选项- 选项非法:返回值为选项字符,optarg 只想选项值字符串
- 选项不非法:返回字符 ‘?’,optopt 保留以后选项字符(谬误)
- 选项非法但短少选项值:返回字符 ‘:’,optopt 保留当权选项字符(谬误)
- 默认状况下:
getopt(...)
对 argv 进行重排,所有操作数位于最初地位
命令行参数编程
main.c
#include <stdio.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
int main(int argc, char *argv[]) | |
{ | |
int i = 0; | |
int c = 0; | |
int iflg = 0; | |
int fflg = 0; | |
int sflg = 0; | |
char *fvalue = NULL; | |
while ((c = getopt(argc, argv, "f:is")) != -1) { // -i,-s, -f 非法,同时 -f 须要携带选项值 | |
switch (c) | |
{ | |
case 'f': | |
fflg = 1; | |
fvalue = optarg; | |
break; | |
case 'i': | |
iflg = 1; | |
break; | |
case 's': | |
sflg = 1; | |
break; | |
case '?': | |
printf("Unknow option: -%c\n", optopt); | |
break; | |
case ':': | |
printf("-%c missing option argmuent\n", optopt); | |
break; | |
case 1: | |
printf("inter: %s\n", optarg); | |
break; | |
default: | |
printf("ret = %d\n", c); | |
break; | |
} | |
} | |
printf("fflg = %d, fvalue = %s, iflg = %d, sflg = %d\n", fflg, fvalue, iflg, sflg); | |
for (i=optind; i<argc; ++i) { // option index, 每解决一个选项,下标 + 1 | |
printf("parameter: %s\n", argv[i]); | |
} | |
return 0; | |
} |
tiansong@tiansong:~/Desktop/linux$ gcc main.c -o main.out | |
tiansong@tiansong:~/Desktop/linux$ ./main.out | |
fflg = 0, fvalue = (null), iflg = 0, sflg = 0 | |
tiansong@tiansong:~/Desktop/linux$ ./main.out -i | |
fflg = 0, fvalue = (null), iflg = 1, sflg = 0 | |
tiansong@tiansong:~/Desktop/linux$ ./main.out abc -f | |
./main.out: option requires an argument -- 'f' // 零碎默认输入 | |
Unknow option: -f | |
fflg = 0, fvalue = (null), iflg = 0, sflg = 0 | |
parameter: abc | |
tiansong@tiansong:~/Desktop/linux$ ./main.out -- abc -f | |
fflg = 0, fvalue = (null), iflg = 0, sflg = 0 | |
parameter: abc | |
parameter: -f | |
tiansong@tiansong:~/Desktop/linux$ ./main.out -v -m -n | |
./main.out: invalid option -- 'v' | |
Unknow option: -v | |
./main.out: invalid option -- 'm' | |
Unknow option: -m | |
./main.out: invalid option -- 'n' | |
Unknow option: -n | |
fflg = 0, fvalue = (null), iflg = 0, sflg = 0 |
optstring 规定的扩大定义
-
起始字符能够是:
:, +, -
或 省略- 省略 → 呈现选项谬误时,程序中通过
:
或?
进行解决并给出谬误提醒 :
→ 谬误提醒开关,程序中通过返回值:
或?
进行解决(无默认谬误提醒)【敞开谬误提醒】+
→ 谬误提醒开关,遇见操作数是,返回 -1,认为选项处理完毕(后续都是操作数)【./demo.out a -v -n -m
, a 之后都为操作数,返回 -1】-
→ 不重排开关,遇见操作数时,返回 1,optarg 指向操作数字符串【默认状况下:getopt(…) 对 argv 进行重排,所有操作数位于最初地位】- 组合 →
+:
or-:
- 省略 → 呈现选项谬误时,程序中通过
批改
main.c
, 敞开默认谬误提醒
while ((c = getopt(argc, argv, ":f:is")) != -1) {
tiansong@tiansong:~/Desktop/linux$ ./main.out -v -m -n | |
Unknow option: -v | |
Unknow option: -m | |
Unknow option: -n | |
fflg = 0, fvalue = (null), iflg = 0, sflg = 0 |
批改
main.c
, 遇见操作数立刻进行返回 -1
while ((c = getopt(argc, argv, "+:f:is")) != -1) {
tiansong@tiansong:~/Desktop/linux$ ./main.out -v abc -m -n | |
Unknow option: -v | |
fflg = 0, fvalue = (null), iflg = 0, sflg = 0 | |
parameter: abc | |
parameter: -m | |
parameter: -n |
批改
main.c
, 不重排命令行参数,遇见操作数返回 1,后继续执行,optarg 指向操作数字符串
while ((c = getopt(argc, argv, "-:f:is")) != -1) {
tiansong@tiansong:~/Desktop/linux$ ./main.out -v abc -m -n | |
Unknow option: -v | |
inter: abc // 返回 1 后,继续执行 | |
Unknow option: -m | |
Unknow option: -n | |
fflg = 0, fvalue = (null), iflg = 0, sflg = 0 |
tiansong@tiansong:~/Desktop/linux$ ./main.out -v abc -m -n def | |
Unknow option: -v | |
inter: abc | |
Unknow option: -m | |
Unknow option: -n | |
inter: def | |
fflg = 0, fvalue = (null), iflg = 0, sflg = 0 |
问题:环境变量是什么?有什么意义?
正文完