1. main函数

  • int main( int argc, char *argv[] );
  • argc是命令行参数的数目,包括程序名在内
  • argv是指向参数的各个指针所构成的数组,即指针数组
  • 当内核执行C程序时(使用exec函数),在调用main前先调用一个特殊的启动例程。可执行程序文件将此启动例程指定为程序的起始地址——这是由连接器设置的,而连接器则是由C编译器调用。启动例程从内核取得命令行参数和环境变量值,然后按上述方式调用main函数做好安排。

2. 进程终止

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

2.1 退出函数

  1. #include <stdlib.h>
  2. void exit(int status);
  3. void _Exit(int status);
  4. #include <unistd.h>
  5. void _exit(int status);
  • _exit(由POSIX.1说明)和_Exit(由ISO C说明)立即进入内核,而exit(由ISO C说明)则先执行一些清理处理,然后返回内核。
  • 3个退出函数都带一个整型参数,称为终止状态退出状态。大多数Unix系统shell都提供检测进程终止状态的方法。
  • 下面几种情况下,该进程的终止状态是未定义的:
    1. 调用这些函数时不带终止状态
    2. main执行了一个无返回值的return语句
    3. main没有声明返回类型为整型

2.2 函数atexit

  1. #include <stdlib.h>
  2. int atexit(void (*func)(void)); // 参数是一个函数指针
  3. Returns: if OK, nonzero on error
  • 按照ISO C的规定,一个进程可以登记多至32个函数,这些函数将由exit自动调用。称这些函数为终止处理程序
  • exit首先调用各终止处理程序,然后关闭所有打开流。exit调用这些函数的顺序与它们登记的顺序相反。
  • 如若程序调用exec函数,则将清除所有已安装的终止处理程序。
  • 注意:内核使程序执行的唯一方法是调用一个exec函数。进程自愿终止的唯一方法是显式或隐式(通过调用exit)地调用_exit或_Exit。进程也可非自愿地由一个信号使其终止。

  • 一个C程序的启动,以及它的各种终止方式

3. 命令行参数

  • 当执行一个程序时,调用exec的进程可将命令行参数传递给新程序。这是Unix shell的一部分常规操作。

4. 环境表

  • extern char **environ; 称environ为环境指针;指针数组为环境表,其中各指针指向的字符串为环境字符串

5. C 程序的存储空间布局

  • 历史沿袭至今,C程序一直由以下几部分组成:

    1. 正文段。这是由CPU执行的机器指令部分。通常,正文段是可由多个应用程序共享的,在存储器中只需一个副本。正文段常常是只读的。
    2. 初始化数据段,也称为数据段。包含了程序中需明确地赋初值的变量。
    3. 未初始化数据段,也称为bss段(block started by symbol,由符号开始的块)。在程序开始执行之前,内核将此段中的数据初始化为0或空指针。
    4. 栈。自动变量以及每次函数调用时所需保存的信息都存放在此段中。
    5. 堆。通常在堆中进行动态存储分配。惯例,堆位于未初始化数据段和栈之间。
  • 一种典型安排方式,这是程序的逻辑布局

  • size命令报告正文段、数据段和bss段的长度(以字节为单位)

    $ size /usr/bin/cc /bin/sh
    text data bss dec hex filename
    346919 3576 6680 357175 57337 /usr/bin/cc
    102134 1776 11272 115182 1c1ee /bin/sh
    第4、5列分别是以十进制和十六进制表示的3段总长度

6. 共享库

  • 共享库使得可执行文件中不再需要包含公用的库函数,而只需要在所有进程都可以引用的存储区中保存这种库例程的一个副本。减少了每个可执行文件的长度,但增加了一些运行时间开销。这种时间开销发生在该程序第一次被执行时,或者每个共享函数库函数第一次被调用时。
  • 另一个优点是可以用库函数的新版本代替老版本而无需对使用该库的程序重新连接编译。

7. 存储空间分配

  • ISO C说明了3个用于存储空间动态分配的函数

    malloc,初始值不确定
    calloc,每一位都初始化为0
    realloc,新增区域内的初始值不确定

  1. #include <stdlib.h>
  2. void *malloc(size_t size);
  3. void *calloc(size_t nobj, size_t size);
  4. void *realloc(void *ptr, size_t newsize);
  5. All three return: non-null pointer if OK, NULL on error
  6. void free(void *ptr);
  • 这3个分配函数所返回的指针一定是适当对齐的,满足最苛刻的对齐要求,使其可用于任何数据对象。
  • 返回通用指针void *
  • 这些分配例程通常用sbrk系统调用实现。该系统调用扩充或缩小进程的堆。虽然sbrk可以扩充或缩小进程的存储空间,但是大多数malloc和free的实现都不减少进程的存储空间。释放的空间可供以后再分配,将它们保持在malloc池中而不返回给内核。
  • 大多数实现所分配的存储空间比所要求的要稍大一些,额外的空间用来记录管理信息——分配块的长度、指向下一个分配块的指针等。
  • 常见错误:1. 释放一个已经释放了的块;2. 调用free时所用的指针不是3个alloc函数的返回值;3. 忘记调用free造成内存泄露。

8. 替代的存储空间分配程序

  • libmalloc
  • vmalloc
  • quick-fit,历史上所使用的标准malloc算法是最佳适配或首次适配存储分配策略。quick-fit算法比上述两种快,但可能使用较多存储空间
  • jemalloc
  • TCMalloc,高性能、高扩展性和高存储效率。开源,是Google-perftools工具中的一个
  • 函数alloca,在当前函数的栈帧上分配存储空间,而不是在堆上。

    优点:当函数返回时,自动释放它所使用的栈帧,不再需要自己释放空间
    缺点:alloca函数增加了栈帧的长度,而某些系统在函数已经被调用后不能增加栈帧长度,于是也就不能支持alloca函数。本书4个平台均支持该函数。

9. 环境变量

  • Unix内核并不查看这些字符串,它们的解释完全取决于各个应用程序。
  • LANG、PATH、HOME、PWD、TERM ...
  1. #include <stdlib.h>
  2. char *getenv(const char *name);
  3. Returns: pointer to value associated with name, NULL if not found
  1. #include <stdlib.h>
  2. int putenv(char *str); // name已存在,替换
  3. Returns: if OK, nonzero on error
  4. int setenv(const char *name, const char *value, int rewrite); // 当name已存在时,根据rewrite参数而覆盖或保持原值
  5. int unsetenv(const char *name); // 即使name不存在也不算出错
  6. Both return: if OK, − on error
  • 这些函数在修改环境表时是如何进行操作的呢?
    1. 删除一个字符串很简单
    2. 但是增加一个字符串或修改一个现有的字符串就困难得多。因为环境表和环境字符串通常占用的是进程地址空间的顶部,故不能向上扩展;而其下方是各栈帧,故也不能向下扩展。两者组合使得该空间的长度不能再增加。

19. 函数setjmp、longjmp

  • 在C中,goto语句是不能跨越函数的,而执行这种类型的跳转功能是函数setjmp和longjmp。它们对于处理发生在很深层嵌套函数调用中的出错情况是非常有用的
  1. #include <setjmp.h>
  2. int setjmp(jmp_buf env);
  3. Returns: if called directly, nonzero if returning from a call to longjmp
  4. void longjmp(jmp_buf env, int val);
  • 直接调用setjmp,返回0;调用longjmp导致程序在setjmp处返回,返回值为val
  • 特殊类型jmp_buf,是某种形式的数组,其中存放在调用longjmp时能用来恢复栈状态的所有信息。

19.1 自动变量、寄存器变量、易失变量volatile

  • 当调用longjmp函数后,在main函数中,自动变量和寄存器变量的状态如何?

    1. 看情况。大多数实现并不回滚这些自动变量和寄存器变量的值,而所有标准则称它们的值是不确定的。
    2. 如果有一个自动变量,而不想其值回滚,可定义为具有volatile属性。
    3. 声明为全局变量或静态变量的值在执行longjmp时保持不变。

19.2 自动变量的潜在问题

  • 在某个函数调用返回后,仍然在使用分配在该函数栈上的变量。

20. 函数getrlimit、setrlimit

  1. #include <sys/resource.h>
  2. int getrlimit(int resource, struct rlimit *rlptr);
  3. int setrlimit(int resource, const struct rlimit *rlptr);
  4. Both return: if OK, − on error
  1. struct rlimit {
  2. rlim_t rlim_cur; /* soft limit: current limit */
  3. rlim_t rlim_max; /* hard limit: maximum value for rlim_cur */
  4. };
  • 在更改资源限制时,须遵循下列3条规则:

    1. 任何一个进程都可将一个软限制更改为小于或等于其硬限制值
    2. 任何一个进程都可降低其硬限制值,但它必须大于或等于其软限制值。这种降低,对普通用户而言是不可逆的
    3. 只有超级用户进程可以提高硬限制值。常量RLIM_INFINITY为无限制
  • resource参数的取值列举:

    RLIMIT_AS 进程总的的可用存储空间的最大长度(字节)
    RLIMIT_CORE core文件的最大字节数
    RLIMIT_FSIZE 可以创建的文件的最大字节长度
    RLIMIT_NOFILE 每个进程能打开的最多文件数
    RLIMIT_NPROC 每个实际用户ID可拥有的最大子进程数
    RLIMIT_STACK 栈的最大字节长度

原创文章,转载请声明出处:http://www.cnblogs.com/DayByDay/p/3911195.html

《Unix环境高级编程》读书笔记 第7章-进程环境的更多相关文章

  1. [置顶] 文件和目录(二)--unix环境高级编程读书笔记

    在linux中,文件的相关信息都记录在stat这个结构体中,文件长度是记录在stat的st_size成员中.对于普通文件,其长度可以为0,目录的长度一般为1024的倍数,这与linux文件系统中blo ...

  2. unix环境高级编程-读书笔记与习题解答-第一篇

    从这周开始逐渐的进入学习状态,每天晚上都会坚持写c程序,并且伴随对这本书的深入,希望能写出更高质量的读书笔记和程序. 本书的第一章,介绍了一些关于unix的基础知识,在这里我不想去讨论linux到底是 ...

  3. unix 环境高级编程-读书笔记与习题解答-第二篇

    第四节 输入与输出 上次的笔记中写到的 open, read, write, lseek 以及close ,都是不带缓存的IO函数,这些函数都使用文件描述符进行工作. 上一篇笔记用到的 read(ST ...

  4. [置顶] 文件io(一)--unix环境高级编程读书笔记

    unix-like(后面以linux为例)系统中的文件操作只需要五个函数就足够了,open.close.read.write以及lseek.这些操作被称为不带缓存的io,这里有必要说一下带缓存和不带缓 ...

  5. unix 环境高级编程 读书笔记与习题解答第四篇

    第一章 第六节 第一小节 这一章没有程序设计和API方面的深入学习,而是注重介绍了unix操作系统中的原始数据类型和系统原型函数,错误处理方面的知识. ____unistd.h____ 该文件包含了u ...

  6. unix进程的环境--unix环境高级编程读书笔记

    http://blog.csdn.net/xiaocainiaoshangxiao/article/category/1800937

  7. unix环境高级编程 读书笔记

    1.上班业余时间把书下载下来,第一章读完了,但是程序只能回家运行啦!Fighting!

  8. Node.js高级编程读书笔记 - 2 文件和进程处理

    Outline 3 文件.进程.流和网络 3.1 查询和读写文件 3.2 创建和控制外部进程 3.3 读写数据流 3 文件.进程.流和网络 3.1 查询和读写文件 path 从Node 0.8起,pa ...

  9. Node.js高级编程读书笔记Outline

    Motivation 世俗一把,看看前端的JavaScript究竟能做什么. 顺便检验一下自己的学习能力. Audience 想看偏后台的Java程序员关于前端JavaScript的认识的职业前端工程 ...

随机推荐

  1. 【工作细节记录】维护项目中前端JS组件丢失后,应如何维护开发之启发

    事因: 我所维护的项目为旧项目,接手项目后并没有什么开发文档留下,导致很多时候一出现问题就需要自己去研究整个过程. 项目中一直使用一个"$.download()"的方法进行文件下载 ...

  2. Qwiklab'实验-CloudFront, EFS, S3'

    title: AWS之Qwiklab subtitle: 3. Qwiklab'实验-CloudFront, EFS, S3' date: 2018-09-21 17:29:20 --- Introd ...

  3. idea--IntelliJ IDEA隐藏不想看到的文件或文件夹

    打开IntelliJ IDEA,File -> Settings -> Editor -> File Types 在红框部分加上你想过滤的文件或文件夹名

  4. tcpsock for Golang

    前记:本文所述的 tcpsock 库托管在 Github. Golang 中的 net 标准库已对 TCP 网络编程作了简洁(却很不简单)的封装,基本上,可直接通过引用其提供的相关接口开发简易的网络应 ...

  5. C语言基本语法——数组

    一.一维数组 1.什么是数组 2.数组语法 3.下标 4.初始化 5.数组名和数组首地址 二.一维数组的应用 1.数组的赋值与拷贝 2.数组的正反遍历 3.随机数 4.数组乱序 5.数组的重复 三.二 ...

  6. python之类的组合

    类的组合 学校与课程没有共同点,课程与老师没有共同点,但是学校与课程有关联,课程与老师有关联:学校.课程.老师是三个完全不同的类:课程是属于学校的,老师是教课程的,此时我们就用到类的组合来关联,学校- ...

  7. git--客户端管理工具初步使用

    说点废话哈 小白一枚, 今年3月份进入自己的第一家公司, 开始成为前端中的一份子,好在公司里有位和我一同进来的一位老哥带着我,从老哥身上学到的知识不多,(因为和老哥只相处工作了三个月,因为家里的事情, ...

  8. 【codeforces 229C】Triangles

    [题目链接]:http://codeforces.com/problemset/problem/229/C [题意] 给你一张完全图; 然后1个人从中选择m条边; 然后另外一个人从中选择剩余的n*(n ...

  9. SQL SERVER-in,between,like

    and 1 LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式 ( 可以使用正则表达式) select * from [User] where UserName like '%r' -- 以 ...

  10. ASP.NET-HTTP管道模型

    HTTP管道模型处理WEB程序很小的一方面.管道模型是类似于Web Services的一种在服务器端处理ASP.NET页面的框架技术 一.管道对象模型 在System.Web的命名空间中处理HTTP的 ...