Linux编程---进程基础
Linux编程---进程基础
进程这个概念大家都很熟悉了吧...我就不多说了..
首先是进程环境.也就是Shell相关的内容.
这都是很基础的我就挑一些我自己都不太清楚的写写.
一.命令行参数
POSIX对命令行的语法约定:
1.实用程序名至少两个,至多9个字符,且只包含小写字母和数字.(Linux应该不止9个吧.我觉得这是Unix下shell的规定).
2.选项名必须是但个字母或者数字,-W选项保留给实现扩展使用,不允许多数字选项.
3.选项和它的选项值可以作为也可以不作为分开的单词.即-ofoo和-o foo是一样的..(我看的达内视频,里面有个老师就喜欢这么写..)
4.如果多个选项均不要求有选项值的话,可以集中在一个短横线分隔符之后作为一个单词,因此’-abc’和’-a -b -c’等价.(貌似鸟哥书上写过...但是我完全忘了...)
5.第一次出现的参数’--’终止所有选项.后继的任何参数均视为操作数.即使他们是以’-’开头的单个字符也是如此.貌似安装程序的时候遇到这个情况比较多...但我记得我一搞写好多个’--’接在后面.
6.多个选项可按任意顺序出现,单个选项也可多次出现,其解释留给应用程序.
7.仅由一个短横线字符组成的单词按操作数解释.UNIX系统约定,它用于指定来自标准输入流的输入或标准输出流的输出.例如,如下命令中,单个短横线’-’是选项参数-o的值,他代表标准输出流,即指定将会变文件输出到标准输出流.
gcc -S file.c -o - -pipe
这个意思我猜是直接把输出输出到NULL文件中...-pipe表示用管道代替过程中的临时文件.我也是第一次晓得这个-pipe参数.这么写了之后比较简单的makefile貌似都可以不写clean了?
是否每个shell程序都要写一个函数来分析这些命令行参数呢?
实际上已经有了库函数帮忙做这件事情了...(原来写过几个小程序都是自己写函数分析的....)
int getopt(int argc,char 8const argv[],const char *optstring);
前两个参数就是main后面的参数.第三个参数就是解析出来串的结果.每次调用一个getopt则获得一个optstring参数.
这个optstring参数可能比较复杂.注意,这里不是提取出参数放到optstring中,而是根据optstring来提取出参数是怎样的..还是举个例子吧.
c=getopt(argc,argv,”:f:is”)
“:f:is”中的顺序不重要.开头的”:”表示在后面遇到错误之后不返回’?’,而是返回’:’.
”f:”表示f这个参数后面要跟一个操作数.
第一次调用optstring的时候会对optstring分析.然后每次遇到f,i,s这三个之一的参数时,就会返回其当得到参数类型(f,i,s之一).返回f的时候,同时会设置optarg.这个optarg是一个全局字符指针.也就是相当于把’:’在命令行中所表示的操作数给optarg.当遇到未知参数的时候,optarg被设置为’?’.同时c也被设置为’?’.
这个函数配置了四个全局变量
optarg----就是解析出来的内容
optind----再次调用getopt的时候要分析argv.这是个下标值.
optopt----最后一个未知选项.
opterr----用来报错.如果在getopt调用之前就设置不为0,并且opstring的开头不是”:”,getopt在遇到位置选项字符或缺少选项所要求的值时,会自动打印一个错误消息到标准错误流中.设置成0的话,将不打印任何错误信息,但仍然返回”?”或”:”指明错误.
我感觉已经解释的差不多了...写完介绍突然觉得好麻烦...还不如自己写函数分析.....
Linux进程控制——exec函数族
Linux进程间通信
Linux进程间通信:消息队列
Linux进程的基本知识
二.环境变量
shell标准环境变量.
HOME 用户的主目录或初始默认目录
LANG 对于地区设置的预定义的名字
LC_COLLATE 字符排序的地区类别名
LC_CTYPE 字符处理的地区类别名
LC_MONETARY 包含有关货币数字编辑信息的地区类别名
LC_NUMERIC 包含数字编辑信息(例如基字字符)的地区类别名
LC_TIME 日期/时间格式信息的地区类别名
LOGNAME 与当前进程相联系的注册名
PATH 可执行文件的路径前缀
TERM 终端类型
TZ 时区信息
每个进程的环境表
extern char ** environ;这是进程的环境变量表指针.
其内容有HOME,PATH,SHELL,USER,LOGNAME这几个环境变量.
访问环境变量
char * getenv(const char *name);
int putenv(char *str);
第一个函数参数就是环境变量的名字.返回环境变量串指针.没什么好说的.
第二个函数则是增加一个环境变量或者去掉一个环境变量的定义.如果参数是name=value的形式.那么就会增加一个环境变量.如果是name已存在,那么就会把旧的定义去掉.同时设置为成新的值.并且不要以局部变量作为字符数组作为str的参数.
补充一点,实际上环境变量在进程虚拟地址空间中是在内核区中的.这一点我是看APUE和百度的一张图结合起来发现的.原来以为环境变量是在栈段上面一个专门的位置空出来存放环境变量.但这几天看书,发现并不是那么一回事.看来自己原来记错了.
三.终止进程
只学过语言的估计觉得在main里面return就足够了吧...但实际上多线程之后return在很多情况下就不合适了.就要用下面的函数了
int exit(int status);
可能有的人还见过_exit.实际上exit就是调用_exit来退出并且返回到内核的.但是实际上在返回到内核之前,还要执行一些清理工作.具体如下:
--按atexit()注册时相反的顺序调用所有注册函数.
--关闭所有打开的流.
--删除用tmpfile()建立的所有临时文件.
--调用exit(status)终止进程.
这里exit的status可以用两个宏来定义.EXIT_SUCCESS和EXIT_FAILURE.其实就是0和1.
int atexit(void (*func)());
表示注册一个函数,到进程正常终止时调用其注册的函数.简单来说相当于进程的析构函数.
我猜对于pthread应该是用atexit注册了一个函数.所以在进程终止的时候就可以关闭线程了.并且查了才知道atexit最多只能注册32个函数.但线程是很多的.估计只能这样了.还有pthread_cleanup_push和pop好像就没有上限限制.应该都是针对线程的注册函数知道的一个变量来操作的吧.
貌似这里可以搞一个恶作剧~可以注册一个函数,这个函数里面通过exec并且把路径传递进去~那么这个进程就永远关不掉了~~~~~如果我要是黑客...我就会搞一下这个~用钩子把原先的位置记录下来,调用一个atexit,然后再把PC寄存器的值还回去~~~当然先得我学会用钩子这种东西再说吧~~~
流产函数
void abort();
这个以执行立即终止程序.并且不用atexit注册的清理函数.但在终止程序之前关闭所有打开的流并生成一个core文件.
所有异常终止程序的原因都是由信号造成的.实际上abort就是通过生成一个SIGABRT信号来流产的.
更多详情见请继续阅读下一页的精彩内容:
|
评论暂时关闭