命令行参数

在C中,main函数有很多的变种,比如

main(),
int main(),
int main(int argc, char *argv[]),
int main(int argc, char *argv[], char *env[])。


在很长一段时间里(特别是在windows下),我都不清楚后面两种main函数中这么多参数有什么用,直到转到linux下,才明白了这些参数并不是多余的。


int main(int argc, char *argv[])。这两个参数也就是我们在命令行中跟在要执行程序名后面的参数。比如 ./necho hello world。参数的个数存储在argc中(在这个例子中是3,necho也算参数),参数的内容存储在argv指向的一个二维数组中(necho存储在二维数组中的第一个位置),参数名后面都以NULL结尾。

使用argv[0]的一点小技巧

在实际工作中,我们可以对一个程序创建多个不同名称的链接。当从不同名称的链接执行该程序时,我们在程序中可以通过argv[0]知道到底是哪个链接在执行该程序,这样我们就可以调用程序的不同部分来执行。这样做的好处是,同一个程序在不同链接名的调用下,表现出不同程序的特性。

 

几种不使用main函数参数来获得命令行参数的用法(不可移植):

1.在linux系统中,可以通过/proc/PID/cmdline来获得命令行参数,但是参数之间的空格被忽略。比如上面例子中,如果cat /proc/PID/cmdline 将会得到./nechohelloworld。如果在程序中可以通过下面代码来获得命令名:

       int fd = open(“/proc/self/cmdline”,  O_RDONLY);

       read(fd, buff, 100);

2.在C库中,为了使程序能知道命令的路径,提供了两个全局变量program_invocation_name, program_invocation_short_name(定义在<errno.h>,必须在程序中定义_GNU_SOURCE)。第一个全局变量提供了命令的完整路径,而第二个只提供了一个命令名。比如/home/share/src/necho和necho。

通常情况下,我们的命令行参数不会多到溢出,不过了解存储该参数的空间大小对编程也没什么坏处。我们可以通过ARG_MAX(定义在<limits.h>)这个宏或者sysconf(_SC_ARG_MAX)系统调用来了解参数空间大小(该空间存储命令行参数和环境变量)。在linux系统上,ARG_MAX曾经被固定的设置为32个页的大小。但是从2.6.32起,该存储空间的大小被定义为RLIMIT_STACK的四分之一。

 

环境变量

每个进程都有相关联的环境列表(Environment List),环境列表由多个环境字符串组成。环境字符串被定义成name=value格式。name叫做环境变量(Environment Variable)。

 

当一个进程被创建时,该进程继承父进程的环境列表。这个特性可以作为父进程和子进程通信的一种方法。比如,当父进程要创建子进程时,可以先设置某个环境变量,子进程随后在自己的环境列表中读取该环境变量。不过这种通信是单向的(one-way)和一次性的(once-only),子进程在创建后,就完全拥有和父进程独立环境列表了。程序可以通过检查环境变量来改变程序的特性(像使用命令行参数一样)。

 

环境变量通常在shell中使用,在shell中创建的进程都继承了shell的环境列表。通常在bash下,我们像下面这样使用环境变量:

export SHELL = /bin/bash

如果只是想设置某一个程序的环境变量,可以这样使用:

name1=var1 name2=var2 nameN=varN program

使用printenv显示当前的环境列表:

$printenv

SHELL=/bin/bash

HOME=/home/ddb

PATH=/usr/local/bin:/usr/bin:/bin:

可以通过cat /proc/PID/environ来查看进程环境列表。

 

程序中如何使用环境列表

1.通过全局变量char **environ。environ和argv很相似。也可以通过

int main(int argc, char *argv[], char *envp[])中的envp来访问。

2.使用程序提供的API。

char *getenv(const char *name)

注意点:

a.该函数返回指定环境变量的字符值。

b.不要直接修改返回值,因为在类UNIX的大部分实现中,返回指针实际上是指向环境字符串中的value部分的。如果要改变该值,使用setenv()或putenv()。

c.当程序得到一个返回指针后,要用一个私有buff来保存该值。因为在某些实现中,该函数内部使用一个静态buff来保存需要返回的值,这使得在下一次函数被调用后,静态buff中的值被其他值覆盖。

 

int putenv(char *string)

注意点:

1.成功返回-0,失败返回-非0(不是-1)。

2.string的格式为”name=value”。

3.不要把string声明成自动变量,string将成为环境列表的一部分,也就是说,该程序不会复制string到环境列表中,而是把string当做列表的一部分,当程序中改变string,会影响该进程的环境变量。

4.使用该函数通常是父进程想让它所创建的子进程继承某个改变的环境变量。或者是想让自己根据改变的环境变量来改变程序的特性(先改变某些环境变量,然后执行exec()函数群来调用自己,程序重启,然后根据这些改变的环境变量来改变程序运行的特性)。

int setenv(const char *name, const char *value, int overwrite)

int unsetenv(const char *name)

注意点:

1.setenv()会创建一个新的buff来存储参数“name=value“(跟putenv对比),我们没必要再name后面或value前面添加”=”号,因为在该函数中会自动添加。

2.只有在overwrite为非0,环境变量才会改变。

 

#define _BSD_SOURCE

int clearenv(void)

注意点:

1.该函数清除整个环境列表。也可以通过environ=NULL来清除。

2.当该函数跟setenv()一起使用时,会产生内存泄露。因为clearenv()不会清除setenv()分配的内存。这两个函数不会频繁的调用,所有通常不是什么大问题。

ABI的讨论

Application Binary Interface是一组规则,它指定了一个二进制程序在运行时如何和内核、库交换信息。ABI指定了交换信息的寄存器和栈位置。一个ABI兼容的程序被编译后,它就可以在所有ABI兼容的系统上运行了。

Linux进程-命令行参数和环境列表相关推荐

  1. 隐藏进程命令行参数,例如输入密码等高危操作

    目录 前言 复写argv参数 获取标准输入 总结 前言 启动程序很多时候用命令行参数可以很方便,做到简化一些配置,但是输入用户名密码等操作,如果通过进程查看工具直接看到密码就太不安全了. 因此很有必要 ...

  2. linux的memmap函数_究竟有多少linux内核命令行参数

    linux启动时可以带命令行参数,这些参数会影响内核乃至启动脚本的行为.在内核中,用early_param(命令行参数名称,命令行参数处理函数)来注册.除了内核参数,还可以有其他的命令行参数,各自有自 ...

  3. linux命令行参数含空格,Linux的命令行参数风格

    在Linux中,几乎所有程序都会提供几个命令行选项,有些程序提供的命令行参数多到咂舌!这样做使得程序的运行非常灵活,而且程序的配置信息可以由脚本指定,这对于作为管道或过滤器的程序尤其重要.有三种约定可 ...

  4. linux c 命令行参数处理函数 getopt()和getopt_long()

    在实际编程当中,自己编写代码处理命令行参数是比较麻烦且易出错的.一般我们会直接使用getopt()和getopt_long()函数,下文将介绍具体的使用方法. getopt() getopt()用于处 ...

  5. linux自定义命令行参数,如何自定义一个Linux命令(简单易懂版)

    好久没写东西了,如果不往外输出,就不知道自己到底经历过什么,学到过什么,简书的第一篇文章从这篇前年写在csdn的文章开启.以下是正文,希望大家能够互相支持,共勉! Linux系统提供了大量的命令供用户 ...

  6. .NET Core采用的全新配置系统[5]: 聊聊默认支持的各种配置源[内存变量,环境变量和命令行参数]...

    较之传统通过App.config和Web.config这两个XML文件承载的配置系统,.NET Core采用的这个全新的配置模型的最大一个优势就是针对多种不同配置源的支持.我们可以将内存变量.命令行参 ...

  7. .NET/C# 获取一个正在运行的进程的命令行参数

    在自己的进程内部,我们可以通过 Main 函数传入的参数,也可以通过 Environment.GetCommandLineArgs 来获取命令行参数. 但是,可以通过什么方式来获取另一个运行着的程序的 ...

  8. python 命令行参数-Python处理命令行参数

    1. 将命令行参数保存在列表中,注意argv[0]是程序本身的名字: import sys print(sys.argv) print(sys.argv[1]) python argv.py loca ...

  9. python 命令行 参数_Python命令行参数

    python 命令行 参数 Python Command line arguments are input parameters passed to the script when executing ...

最新文章

  1. linux 搜索so文件,Linux下查找和安装依赖的.so文件
  2. 【题解】P1080 国王游戏(贪心+高精python天下第一)
  3. 【转】线性代数的几何意义
  4. 【TypeScript】使用 const 关键字声明只读变量
  5. JavaScirpt类型检测函数总结
  6. 雅虎公司C#笔试题(之二)
  7. cenos 安装 phpredis 扩展
  8. Spring Boot的学习之路(02):和你一起阅读Spring Boot官网
  9. open cv+C++错误及经验总结(五)
  10. Mybatis一对一和一对多配置
  11. Linux内核入门(四)—— 内核汇编语言规则
  12. oracle数据库建语句吗,Oracle建表语句是什么_数据库
  13. win10-如何管理开机启动项?
  14. 高等代数期末考试题库及答案_高等代数试题及答案
  15. 不同主机之间通过XDMCP协议通信(X-server和X-client不在同一主机)
  16. 论文被多人研究过了,我还可以怎么写?
  17. docker容器-nginx conf文件使用环境变量值
  18. Joel谈优秀软件开发-摘录
  19. 手工实现:SVM with Stochastic Gradient Descent
  20. 继承 super的讲解

热门文章

  1. 私房库视频学习笔记-小清新BBS系统开发技术归纳
  2. JAVA NIO之Direct Buffer 与 Heap Buffer的区别?
  3. TimeoutException
  4. pentaho中Invalid byte 3 of 3-byte UTF-8 sequence的解决方法
  5. 参加51CTO学院软考培训,我通过啦!
  6. 蓝牙Bluetooth技术小知识
  7. cocos2d-x JS 开启远程代码调试
  8. Android 搜索框 search dialog 和 search widget
  9. pycharm小白使用指南
  10. Linux之mount命令详解