【环境变量】命令行参数 | 概念 | 理解 | 命令行参数表 | bash进程

目录

四组概念

命令行参数概念&理解

查看命令函参数

命令行字符串&命令行参数表

命令行参数存在的意义

谁形成的命令行参数

父进程&子进程&数据段

bash进程


最近有点小忙,可能更新比较慢。

四组概念

  • 竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级。
  • 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰。
  • 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行。
  • 并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。

并发:在特点的时间范围内,一个CPU调度进程,多进程以上下文切换的方式保证进程同时得以推进。

用户层出现卡顿的情况❓

回答:在运行队列中排队的进程很多,CPU切换的负担过重,出现进程被再次调度的时间很长,或者长时间不被调度的情况,出现进程的卡顿,也就是用户层出现卡顿的情况。


并行:并行的同时存在并发。并发切换速度非常快,用户层感知不到的。并发的历史价值是指多个CPU能让多个进程同时运行,既便宜又能满足用户的需求。(软件技术带来的意义)


独立性(地址空间细讲):任务启动变成进程,多进程运行,进程和进程之间是不影响的。数据的独立(全局/局部,but全局变量可以被子进程看到,局部不可以)


**竞争性:**硬件资源优先(只有一套),进程是非常多的,进程通过访问硬件来达到自己的任务目的,进程在资源本质上天然就是具有竞争性的。

命令行参数概念&理解

main()函数可以接收参数,这些参数是什么❓表示的什么意义❓ 为什么存在❓

  • main函数的参数可带参数,也可以不带参数(这里讨论带参的)
  • int main ( int argc, char *argv[ ] )
  • 参数 int argc, char *argv[ ]
  • 参数就是命令行参数的形式参数;命令行中输入的是实际参数
  • int argc 表示指针数组中元素的个数有多少(c count)
  • char *argv 表示指针数组(数组中每个元素都是char *类型的元素)
  • >>>>>>char *类型的指针
  1. 指向某个字符的地址
  2. 指向某个字符串的起始地址
  • 在char *argv[ ]中char *类型的元素通常是指向字符串的起始地址的
  • char *argv[ ]的最后一个指针必须指向NULL
  • argc 是不包括NULL的个数的
  • 命令行输入的参数会存在程序

综下总结:命令行参数是C语言提供的一种可以 以main函数传参的方式 支持用户去实现一些可变选项的一些程序 的方式。(同一个程序以不同选项实现不同功能)

查看命令函参数

编译运行我们发现

  • argc中的元素就是命令行中输入的是参数,即命令行参数
  • argc是根据命令行输入的参数变动的大小的
  • argc 是不包括NULL的个数的
  • char *argv[ ] 是变长数组
  • 命令行输入的参数会存在程序(自己的程序a.out 或者 系统的指令程序)和程序匹配的选项
cpp 复制代码
#include<stdio.h>
#include<unistd.h>
int main(int argc,char *argv[])
{
    for(int i = 0;i < argc;i++)
    {
        printf("argv[%d]->%s\n",i,argv[i]);
    }
    return 0;
}

命令行字符串&命令行参数表

  • 整体:命令行字符串
  • 局部:程序的路径&名称 + 和该进程匹配的选项(或者只有程序的路径&名称)
  • 程序:分为用户自己写的程序&选项 和 系统的程序&选项
  1. 用户在命令行输入的参数整体是一个命令行字符串。
  2. 由OS中的进程/模块负责以空格为分割线分割成1个1个字符串(把字符串变成"\0")。
  3. OS中的进程/模块 把这些字符串的地址传给argv数组,形成命令行参数表,argv中的元素都指向这些字符串。
  4. 再以参数的形式传给子进程的main函数。
  5. 命令行参数表前面都是有效字符串的地址,最后必须以NULL收尾。

【自己程序&选项】

【系统程序&选项】

【验证argc以NULL收尾】

cpp 复制代码
#include<stdio.h>
#include<unistd.h>
int main(int argc,char *argv[])
{
    for(int i = 0;argv[i];i++)
    {
        printf("argv[%d]->%s\n",i,argv[i]);
    }
    return 0;
}

【命令行参数表】

命令行参数存在的意义

为什么要这么干❓main函数存在的意义❓

回答:通过给同一个可执行程序带上不同的选项,从而实现让同一个程序根据不同的选项执行不同的功能。

  • 不同的选项 ≈ 不同的子功能 ≈ argc >= 2
  • argc是多少,argv数组就有多少个元素(不包括NULL)
  • 命令行参数本质是交给我们程序的不同的选项,用来定制不同的程序功能。命令中会携带很多的选项。
cpp 复制代码
#include<unistd.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        printf("Usage: %s -[a,b,c,d]\n", argv[0]);
        return 1;
    }
    if(strcmp(argv[1], "-a") == 0)
    {
        printf("this is function1\n");
    }
    else if(strcmp(argv[1], "-b") == 0)
    {
        printf("this is function2\n");
    }
    else if(strcmp(argv[1], "-c") == 0)
    {
        printf("this is function3\n");
    }
    else if(strcmp(argv[1], "-d") == 0)
    {
        printf("this is function4\n");
    }
    else
    {
        printf("no this function!!\n");
    }
   return 0;
}

谁形成的命令行参数

到底是谁这么干的❓

回答:bash进程。

父进程&子进程&数据段

看到下面代码执行的结果,我们发现:子进程是可以拿到父进程的数据(无论是局部变量还是全局变量) 。无论是父进程还是子进程运行时都可以看到1000和7。

  • 父进程的数据默认能被子进程看到并访问。(访问 ≠ 子进程不能修改)
  • 我们发现父进程的pid一直在变化,但是ppid没有改变,一直都是2836
  • 2836是谁❓就是命令行解释器☞bash进程
cpp 复制代码
#include<string.h>
#include<unistd.h>
int g_val = 100000;

int main()
{
    int key=7;
    printf("I am father process, pid: %d, ppid: %d, g_val: %d\n", getpid(), getppid(), g_val);
    sleep(5);

    pid_t id = fork();
    if(id == 0)
    {
        //child
        while(1)
        {
            printf("I am child process, pid: %d, ppid: %d, g_val: %d,key=%d\n", getpid(), getppid(), g_val,key);
            sleep(1);
        }
    }
    else
    {
        // father
        while(1)
        {
            printf("I am father process, pid: %d, ppid: %d, g_val: %d\n", getpid(), getppid(), g_val);
            sleep(1);
        }
    }
}

bash进程

  • OS启动的时候都会启动一个进程☞bash进程
  • 命令行中无论是启动自己的程序,还是系统程序。都会变成进程,起始都是bash的子进程。
  • 命令行中输入的参数默认是输入给bash进程的获取的。
  • 注意❗:系统指令程序和自己程序启动运行都是一样,并没有任何差别(唯一差别启动时,带与否路径,下篇环境变量讲)
  • bash进程获取到了参数
  1. 创建子进程
  2. 形成命令行参数表
  3. 把参数传参给子进程的main函数
  4. 或者父进程的命令行参数表(数据段)是可以被子进程共享的

  • bash进程把命令行参数表传给子进程两种方式
  1. 传参
  2. 父进程的命令行参数表(数据段)是可以被子进程共享的

流程

  • 登录Linux系统
  • 创建bash进程
  • 在命令行中输入参数
  • bash进程获取参数的路径&可执行程序(怎么获取❓下篇)
  • 创建子进程
  • bash并把【命令行参数表】传给子进程main函数(传参 / 共享)
  • 子进程接着执行自己的代码

🙂感谢大家的阅读,若有错误和不足,欢迎指正。

相关推荐
小陈phd11 分钟前
Vscode LinuxC++环境配置
linux·c++·vscode
运维&陈同学14 分钟前
【zookeeper01】消息队列与微服务之zookeeper工作原理
运维·分布式·微服务·zookeeper·云原生·架构·消息队列
是阿建吖!15 分钟前
【Linux】进程状态
linux·运维
hzyyyyyyyu28 分钟前
内网安全隧道搭建-ngrok-frp-nps-sapp
服务器·网络·安全
明明跟你说过43 分钟前
Linux中的【tcpdump】:深入介绍与实战使用
linux·运维·测试工具·tcpdump
Komorebi.py2 小时前
【Linux】-学习笔记05
linux·笔记·学习
Mr_Xuhhh2 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
中云DDoS CC防护蔡蔡3 小时前
微信小程序被攻击怎么选择高防产品
服务器·网络安全·微信小程序·小程序·ddos
HPC_fac130520678164 小时前
以科学计算为切入点:剖析英伟达服务器过热难题
服务器·人工智能·深度学习·机器学习·计算机视觉·数据挖掘·gpu算力