进程环境

进程终止方式

正常终止

1) 从main返回
2) 调用exit
3) 调用_exit或_Exit
4) 最后一个线程从其启动例程返回
5) 从最后一个线程调用pthread_exit

异常终止

1) 调用abort
2) 接收到一个信号
3) 最后一个线程对取消请求做出响应

备注
main函数返回一个整型值和用该值调用exit是等价的,因为启动例程会在main返回后立即调用exit函数(exit(main(argc, argv))
_exit和_Exit立即进入内核,exit函数总是执行一个标注IO库的清理关闭操作:首先调用各终止处理程序,然后关闭所有已经打开的流(正是因为调用了fclose,所以才会将输出缓冲区中的所有数据都冲洗)然后返回内核。

exit()最后也会调用_exit(),但是调用exit()之前,还做了其他工作:
(1)执行用户通过atexit或on_exit定义的清理函数;
(2)关闭所有打开的流,所有的缓存数据均被写入;
(3)调用_exit().

终止处理程序由atexit来声明,被声明的函数由exit自动调用。exit调用这些函数的顺序与他们登记时候的顺序相反。同一个函数如果登记多次,也会被调用多次。

在这里插入图片描述
内核使程序执行的唯一方法是调用一个exec函数,进程资源终止的唯一方法是显式或者隐式地(通过调用exit)调用_exit函数或者_Exit()。进程也可以非自愿地由一个信号使其终止。

argv[argc]为NULL,就像我们使用exec一样。

参数传递

当执行一个程序时,调用exec的进程可将命令参数传输传递给该新程序。

进程环境

每个进程都拥有一个环境表,与参数表一样,环境表也是一个字符指针数组,其中每个指针包含一个以null结束的C字符串的地址。全局变量exviron则包含了该数组的地址。
在这里插入图片描述
注意最后一项为空。
预定义宏名是完全由大写字母组成。

UNIX内核并不查看这些字符串,它们的解释完全取决于各个应用程序。我们通常在一个shell启动文件中设置环境变量以控制shell的动作

getenv

用于获得环境变量值,因此查看一个值的时候应用使用该函数,而不是使用environ变量。但是如果要查看所有的环境变量,则必须使用environ指针。

对于环境变量而言,我们影响的只是当前进程以及其后生成的和调用的任何子进程的环境,但不能影响父进程。

putenv

putenv取形式为name=value的字符串,将其放到环境表中,如果name已经存在,则先删除其原来的定义。

setenv

setenv将name设置为value,如果在环境表中已经存在,1)rewrite非0,则首先删除现有的定义;2)rewrite为0,则不删除现有定义(name不设置为新的value,而且也不出错。)

unsetenv

unsetenv删除name的定义,即使不存在这种定义也不算出错。

其中putenv和setenv是有区别的,setenv必须分配存储空间,以便依据其参数创建name=value字符串,putenv可以自由地将传递给它的参数字符串直接放到环境中。因此将栈中的字符串传递给putenv时会发生错误,其原因是,从当前函数返回时,其栈帧占用的存储区可能将被复用。

在C语言中,goto语句是不能跨越函数的,而执行这种类型的跳转功能可以使用函数setjmp和longjmp
每个进程都有一组资源限制,其中一些可以用getrlimit和setrlimit函数查询和更改

内存布局

正文段:这是CPU执行的机器指令部分、只读常量,通常,正文段是可共享的,所以即使是频繁执行的程序在存储器中也只需要一个副本,另外正文段常常是只读的,以防止程序由于意外而修改其指令。
初始化数据段:通常将此段称为数据段,它包含了程序中明确赋初值的变量
未初始化数据段(bss段):在程序开始执行之前,内核将此段中的数据初始化为0或者空指针。
:又叫做堆栈,费静态局部变量、函数参数、返回值等等,栈是向下增长的
:用于程序运行时动态存储分配,堆是向上增长的。
内存映射段:是高效的IO映射方式 ,用于装载一个共享的动态内存库,用户可以使用系统提供的接口创建一个共享内存来实现进程间通信。
在这里插入图片描述
在这里插入图片描述
对于32位Intel x86处理器上的linux,正文段从0x08048000单元开始,栈底则在0xc0000000之下开始,堆顶和栈顶之间未用的虚地址空间很大。

未初始化数据段的内容并不存放在磁盘程序文件中,其原因是,内核在程序开始运行前将他们都设置为0。需要存放在磁盘程序文件中的段只有正文段和初始化数据段。

size命令用于报告正文段、数据段和bss段的长度。

使用动态库的时候,程序第一次执行或者第一次调用某个函数的时候,用动态链接方法将程序与动态链接库相链接。减少了可执行文件的长度,但增加了运行时间开销。这种时间开销只发生在该程序第一次被执行时,或者每个共享函数库第一次被调用时。共享库的另一个优点是可以用库函数的新版本代替老版本而无需对使用该库的程序冲重新链接。

存储空间的分配

malloc

分配指定字节数的存储区。此存储区中的初始值不确定。

calloc

为指定数量指定长度的对象分配存储空间,初始化为0

realloc

增加或减少以前分配的长度,当增加长度时,可能需将以前分配的内容移到另一个足够大的区域,以便在尾端提供增加存储区,而新增区域内的初始值不确定。
若realloc的ptr是空,那么就相当于malloc函数。
realloc可能导致野指针的产生。
realloc的最后一个参数是存储区的新长度,不是新、旧存储区长度之差。作为一个特例,若ptr是一个空指针,则realloc的功能与malloc相同,用于分配一个指定长度为newsize的存储区。

free

释放ptr指向的存储空间,被释放的空间通常被送入可用存储区池,以后,可在调用上述3个分配函数时再分配。

常见错误

释放一个已经释放了的块;调用free时所用的指针不是3个alloc函数的返回值;malloc了内存,但是没有free,那么该进程占用的存储空间就会连续增加,这被称为泄漏。如果不调用free函数释放不再使用的空间,那么进程地址空间长度就会慢慢增加,直到不再有空闲空间。此外,由于过快的页开销,会造成性能下降。

sbrk可以扩充或缩小进程的存储空间,但是大多数的malloc和free的实现都不减少进程的存储空间。释放的空间可供以后再分配,但将它们保持在malloc池中而不返回给内核。

进程的资源限制

进程的资源限制通常是在系统初始化时由0进程建立的,然后由后续进程继承。
更改的前提:
1) 任何一个进程都可以将软限制值更改为小于或等于其硬限制值
2) 任何一个进程都可降低其硬限制值,但它必须大于或等于其软限制值。这种减低对于普通用户而言是不可逆的。
3) 只有超级用户进程可以提高硬限制值

errno

只要一个UNIX函数中有错误发生,全局变量errno中就被置为一个指明该错误类型的正数,函数本身返回-1,errno的值只在函数发生错误的时候被设置,如果函数不返回错误,errno的值就没有定义,errno的所有正数错误值都是常值,具有以“E"开头的全大写字母名字,通常在<sys/errno.h>头文件中定义。值0表示没有任何错误。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值