关于linux:Linux系统编程训练营4进程参数编程

33次阅读

共计 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

问题:环境变量是什么?有什么意义?

正文完
 0