UNIX环境高级编程(3) 第七章

7 进程环境

7.2 main函数

C程序总是从main函数开始执行的。当内核执行C程序时(使用exec函数)再调用main函数钱先调用一个特殊的启动例程。

7.3 进程终止

有8种方式使进程终止(termination),其中5中为正常终止,3种异常终止:
1. 从main函数返回;
2. 调用exit;
3. 调用_exit或_Exit;
4. 最后一个线程从其启动例程返回;
5. 从最后一个线程调用pthread_exit。
6. 调用abort;
7. 接到一个信号;
8. 最后一个线程对取消请求作出响应;

  • [x] 退出函数
#include <stdlib.h>
void exit(int status);
void _Exit(int status);
#include <unistd.h>
void _exit(int status);

后两个推出函数直接进入内核,而exit则先执行一些清理处理,比如所有打开流会调用fclose函数,然后返回内核。
main函数中调用exit(0)和return(0)等价。
- [x] 函数atexit

#include <stdlib.h>
int atexit(void (*func)(void));
    return: 0; error: !0.

其中,参数是一个函数地址,当调用此函数时无需向它传递任何参数,也不期望它的返回值。exit调用这些函数与它们登记的顺序相反。
同一函数被登记多次,同样会被调用多次。

7.4 命令行参数

当执行一个程序时,调用exec的进程可将命令行参数传递给该新程序。如
int main(int argc, char *argv[])

7.5 环境表

每个程序都接收到一张环境表,字符指针数组,每个指针包含一个以NULL结束的C字符串。全局变量environ包含了该指针数组的地址:
extern char **environ;

  1. 每个程序都有一个环境表,与参数表一样,环境表也是一个指向字符串在二级指针char **,指向的在环境包括HOME PATH SHELL USER等。
    UNIX中可用size报告正文段/数据段/和bss段的长度(以字节为单位),如size a.out
    !imagedataurl size.png
    C:\Users\KingsPC\Pictures\典型存储器安排.png

7.6 C程序在存储布局

正文段,控制程序在执行在代码,比如函数,正文段是共享,只读
.data段 在定义时候被赋值的全局变量 存储的段,其内容保寸在磁盘上,需要时再写到内存上
.bss段 未初始化在全局变量 ,其内容会由操作系统设置为0或空指针,其内容不保持在磁盘上
.栈 保存函数相关的信息
.堆 动态存储分配区,比如malloc申请在存储区

7.7 共享库

共享库优点减少了可执行文件在长度,缺点要增加了运行时间在开销。这种开销发生在第ta一次被执行时,原因不清楚。
-static 静态编译 编译时复制粘贴重复展开
使用无共享库的方式创建可执行文件: gcc -static hello.c -o hello
默认是使用共享库创建可执行文件的:gcc hello.c -o hello

-5. 自动变量,寄存器变量和易失变量和-O选项。
不进行优化(-O), 自动变量,寄存器变量和易失变量,全局变,局部静态变量全部放在存储器中;
优化后自动变量和寄存器变量都放在寄存器中,volitale变量仍在存储器中。

7.8 3个动态分配的储存空间的函数

#include <stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nobj, size_t size);
    分配若干个每个大小固定的存储空间
void *realloc(void *ptr, size_t newsize);
    all return: 非空指针;error: NULL
    newsize是新的和旧的总长度更改以前分配区的长度。如果往高位有足够的新分配空间,就直接在当前位置增加新空间。没有的话,将当前内容与新分配内容一同放置到一个其他位置,删除原位置内容。所以不应分配指向他的指针
void free(void *ptr); 释放指针

7.9 环境变量

unix内核并不关心这种字符串的意义,它们的解释完全取决于各个应用程序.

#include <stdlib.h>
char *getenv(const char *name);
    return:指向name关联的value指针;error: NULL.

int putenv(char *str);
    return:0;error:!0.

int setenv(const char *name, const char *value, int rewrite);
int unsetenv(const char *name);
    return: 0, error: -1.

7.10 setjmp和longjmp函数

C中没有GOTO语句,使用setjmp和longjmp执行跳转功能.这两个函数对于处理发生在很深的嵌套函数调用中的出错情况非常有用.
setjmp函数确定的是出错之后返回到的main函数中的位置,longjmp是若出错,则从该longjmp处返回到main函数中的
setjmp处。二者关联确定是同一组的标志是setjmp的参数与longjmp的第一个参数,需要是同样值,longjmp的第二个参数则用
来区分其与setjmp相对应的longjmp里的不同出错位置,所以需要设定为不同整数值进行区分。如果需要返回setjmp保存原来的
值,就需要在变量前加volatile属性,优化执行就可以实现其值不回滚.
* volatile:作为关键字,中文意思为易失变量,确保本条指令不会因为编译器优化而忽略,而是每次直接读值。
简单的理解就是这个变量可能会被外部函数改变,为了让这个改变能有效执行,不被编译器优化掉。
举个例子吧,一个函数用了一个外部的变量,但这个变量在此函数中没有改变,只是引用,这时候编译器会去做优化,
把它的值暂放在内部寄存器中,用的时候读取的是寄存器的值,而不是去访问它的地址取值,这样的话,当这个变量
在外部发生了变化的时候,比如中断,或者另外的进程等等。但在这个函数里面就不能起作用,因为被优化后使用的
是寄存器的值,还是原来的值,导致错误发生。这种情况下,就要加上这个定义,就不会被优化了。

7.11 getrlimit和setrlimit函数:

每个进程都有一组资源限制,其中某一些可以用getrlimie和setrlimit函数查询和更改:

#include <sys/resource.h>
int getrlimit(int resource, struct rlimit *rlptr);
int setrlimit(int resource, const struct rlimit *rlptr);
    return: 0; error: 非0.

struct rlimit{
    rlim_t rlim_cur; /*soft limit: current limit */
    rlim_t rlim_max; /* hard limit:maximum value for rlim_cur */
}

对上两个函数的每次调用都指定一个资源以及一个指向rlimit的结构指针。

在更改资源限制时,须遵循下面3条规则:
1. 任何一个进程都可将一个软限制值更改为小于或等于其硬盘限制值。
2. 任何一个进程都可降低其硬限制值,但它必须大于或等于其软限制值。这种降低,对普通用户而言是不可逆的。
3. 只有超级用户进程可以提高硬限制值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值