【环境变量】命令行参数 | 概念 | 理解 | 命令行参数表 | 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函数(传参 / 共享)
  • 子进程接着执行自己的代码

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

相关推荐
ICscholar42 分钟前
ExaDigiT/RAPS
linux·服务器·ubuntu·系统架构·运维开发
sim20201 小时前
systemctl isolate graphical.target命令不能随便敲
linux·mysql
薛定谔的猫19821 小时前
RAG(二)基于 LangChain+FAISS + 通义千问搭建轻量级 RAG 检索增强生成系统
运维·服务器·langchain
米高梅狮子2 小时前
4. Linux 进程调度管理
linux·运维·服务器
再创世纪2 小时前
让USB打印机变网络打印机,秀才USB打印服务器
linux·运维·网络
fengyehongWorld3 小时前
Linux ssh端口转发
linux·ssh
昨夜见军贴06164 小时前
IACheck AI审核如何实现自动化来料证书报告审核,全面提升生产效率与合规水平
运维·人工智能·自动化
知识分享小能手5 小时前
Ubuntu入门学习教程,从入门到精通, Ubuntu 22.04中的Shell编程详细知识点(含案例代码)(17)
linux·学习·ubuntu
浩子智控5 小时前
电子产品设计企业知识管理
运维·服务器·eclipse·系统安全·硬件工程
以太浮标5 小时前
华为eNSP模拟器综合实验之-BGP路由协议的配置解析
服务器·开发语言·php