【Linux】main函数的参数列表从何而来?

Linux系统进程通过exec系列函数启动新程序时,argc整型 、 argv数组 和 环境变量表 environ 会作为 exec 系列函数的参数,显式传递给新程序的 main 函数。

main函数的参数列表

在C语言中,main函数的标准参数列表通常如下所示:

c++ 复制代码
int main(int argc, char *argv[], char *env)
{
    // 函数体
}

其中:

  • argc:表示命令行参数的数量(包括程序名本身)。

  • argv:是一个字符指针数组,包含了所有命令行参数的字符串表示。

  • env:环境变量表

参数来源及底层原理

1. argc
  • 来源argc(Argument Count)表示传给程序的命令行参数的数量。这个数量包括了程序本身的名称作为第一个参数。
  • 底层原理 :当调用exec系列函数时,会将一个整数参数 argc ,传递新程序的main函数,表示参数的数量。
2. argv
  • 来源argv(Argument Vector)是一个字符指针数组,包含了所有命令行参数的字符串表示。每个元素是一个字符串,表示一个命令行参数。
  • 底层原理 :当调用exec系列函数时,会将一个字符指针数组 argv ,传递新程序的main函数,这个数组包含了所有的命令行参数。
3.env
  • 来源 :父进程获取当前进程PCB中的环境变量表,通过调用exec系列函数,显式传递给子进程,这样子进程就"继承"了父进程的环境变量表

示例代码

下面是一个简单的示例代码,展示了如何通过exec系列函数传递命令行参数:

(注:注释很详细了,若有疑问,可以评论区讨论)

c++ 复制代码
#include <stdio.h> // 包含标准输入输出库,用于printf和fprintf函数
#include <unistd.h> // 包含UNIX标准函数定义,用于fork和execve函数
#include <sys/types.h> // 包含数据类型定义,用于定义pid_t类型
#include <sys/wait.h> // 包含等待子进程状态的函数和宏定义,用于waitpid和WIFEXITED
#include <stdlib.h> // 包含标准函数库,用于exit函数

int main() {
    pid_t pid; // 定义pid_t类型的变量pid,用于存储子进程的进程ID
    char *args[] = {"/bin/echo", "Hello, world!", NULL}; // 定义execve函数的参数数组,指定要执行的命令和参数

    // 获取当前环境变量数组
    char **environ = environ;

    // 使用fork函数创建子进程
    pid = fork();
    if (pid < 0) {
        // 如果fork失败,输出错误信息并退出程序
        fprintf(stderr, "Error: Could not fork.\n");
        exit(1);
    }

    // 如果pid为0,表示当前是子进程
    if (pid == 0) {
        // 在子进程中调用execve函数,执行/bin/echo命令并传递参数
        if (execve(args[0], args, environ) == -1) {
            // 如果execve执行失败,输出错误信息并退出子进程
            fprintf(stderr, "Error: Could not execute %s.\n", args[0]);
            exit(1);
        }
    } 
    else {
        // 如果pid大于0,表示当前是父进程
        // 父进程等待子进程结束
        int status;
        waitpid(pid, &status, 0); // 使用waitpid函数等待子进程结束,并获取子进程的退出状态
        if (WIFEXITED(status)) { // 检查子进程是否正常退出
            // 如果子进程正常退出,打印退出状态码
            printf("Child process exited with status %d.\n", WEXITSTATUS(status));
        }
    }

    return 0; // 程序正常退出,返回0
}

为什么argv[0]需要是程序名字?

程序的名字作为 argv[0] 是一种约定,使得程序可以知道自己被调用时的名字。这对于程序来说非常重要,因为:

  • 调试和日志记录:程序可以打印自己的名字来帮助调试或记录日志。
  • 命令行工具:很多命令行工具需要知道自己被调用时的名字,以便处理特定的行为或提供帮助信息。

同时保证了一致性:这种做法在大多数操作系统和编程环境中是一致的,因此程序员可以依赖这种约定来编写可移植的代码。

相关推荐
小糖学代码7 小时前
LLM系列:1.python入门:3.布尔型对象
linux·开发语言·python
shizhan_cloud7 小时前
Shell 函数的知识与实践
linux·运维
Deng8723473487 小时前
代码语法检查工具
linux·服务器·windows
霍夫曼9 小时前
UTC时间与本地时间转换问题
java·linux·服务器·前端·javascript
2301_810746319 小时前
CKA冲刺40天笔记 - day20-day21 SSL/TLS详解
运维·笔记·网络协议·kubernetes·ssl
❀͜͡傀儡师9 小时前
docker 部署 komari-monitor监控
运维·docker·容器·komari
物联网软硬件开发-轨物科技10 小时前
【轨物方案】软硬件一体赋能,开启矿山机械远程智慧运维新篇章
运维
月熊10 小时前
在root无法通过登录界面进去时,通过原本的普通用户qiujian如何把它修改为自己指定的用户名
linux·运维·服务器
大江东去浪淘尽千古风流人物10 小时前
【DSP】向量化操作的误差来源分析及其经典解决方案
linux·运维·人工智能·算法·vr·dsp开发·mr
打码人的日常分享11 小时前
智慧城市一网统管建设方案,新型城市整体建设方案(PPT)
大数据·运维·服务器·人工智能·信息可视化·智慧城市