07.进程环境

1、main()函数

  • 内核执行C程序时(使用一个exec函数),先调用一个特殊的启动例程(编译器调用连接编辑器,连接编辑器设置启动例程地址),启动例程从内核取得命令行参数和环境变量值。

2、进程终止

  • 8种方式
    • 1.main()返回
    • 2.exit()
    • 3._exit()或_Exit()
    • 4.最后一个线程从启动例程返回
    • 5.最后一个线程调用pthread_exit()
    • 6.调用abort()
    • 7.接收到一个信号
    • 8.最后一个线程对取消请求做出响应
2.1、退出函数
#include <unistd.h>
void _exit(int status);//POSIX.1说明的

#include <stdlib.h> //ISO C说明的
void exit(int status);
void _Exit(int status);
  • exit()先执行一些IO库的清理关闭操作(对所有打开流调用fclose),_[eE]exit立即进入内核
  • status为终止状态,这些情况终止状态未定义:
    • a.调用时不带终止状态
    • b.main执行了无返回值的return语句
    • c.main()没有声明返回类型为整型
2.2、atexit
int atexit(void (*function)(void));
  • ISO C规定,一个进程可以登记至多32个函数,由exit()调用(登记时相反的顺序)
  • 内核使程序执行的唯一方法是调用exec函数,进程自愿终止的唯一方法是显示或隐式的调用[ _][eE]xit,也可由信号终止

3、命令行参数

  • ISO C和POSIX.1都要求argv[argc]是一个空指针,这时我们可以将循环改写成:
    for(i = 0, argv[i] != NULL, i++);
    

4、环境表

  • 每个程序都接收一张环境表(字符指针数组)
    extern char **environ;
    char *getenv(const char *name);
    int putenv(char *string);
    

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

  • C语言一直由下面几部分组成
    • 1.正文段
    • 2.初始化数据段.data
    • 3.未初始化数据段.bbs
    • 4.堆
    • 5.栈
  • a.out 中还有其他类型的段,如符号表段、含调试信息的段、动态共享库链接表段等,并不装载到进程执行的程序映像中
  • 可以size命令查看 .text .data .bss段的长度

6、共享库

  • gcc的 -static阻止使用共享库

7、存储空间分配

#include <stdlib.h>
void *malloc(size_t size);
void free(void *ptr);
void *calloc(size_t nmemb, size_t size);
void *realloc(void *ptr, size_t size);
  • relloc()增加分配区的长度时,可能需要移动到更大的区域,新增区域内的初始值不确定
  • free释放的空间进入存储区池
  • realloc()可能会移动指针,所以不应使任何指针指在该区域
    • ptr为空时功能等价于malloc
  • 在动态分配的缓冲区前或后进行操作,破坏的可能不仅仅是该管理记录信息,它很可能用于其他动态分配的对象
7.1、替代的存储空间分配程序
  • libmalloc:基于SVR4的UNIX系统
  • vmalloc:Vo[1996]。允许进程对于不同的存储区使用不同的技术
  • quick-fit:标准malloc算法是最佳适配或首次适配存储分配策略
  • jemalloc:FreeBSD 8.0中默认存储空间分配程序
  • TCMMalloc:提供高性能、高扩展性和高存储效率…
  • alloca:调用序列与malloc相同,但是它在当前函数的栈帧上分配存储空间

8、环境变量

char *getenv(const char *name);
int putenv(char *string);
int setenv(const char *name, const char *value, int overwrite);
int unsetenv(const char *name);
  • getenv返回一个指针,最后不要直接访问environ
  • putenv取形式为name=value的字符串放到环境表中,放在栈中的参数做参数会出错
  • setenv将name设置为value
  • unsetenv删除name的定义
  • 修改环境是怎么进行的:(考虑环境表和字符串放在进程地址空间的顶部)

9、setjmp()和longjmp()

int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);
  • goto语句不能跨函数,longjmp可以
  • longjmp跳转到setjmp时自动变量和寄存器的值是否回滚是不确定的
    • 全局变量、静态变量和易失变量不受优化的影响
    • 编写非局部跳转的可移植程序时必须使用volatitle属性

10、getrlimit()和setrlimit()

#include <sys/time.h>
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);
int prlimit(pid_t pid, int resource, const struct rlimit *new_limit,
            struct rlimit *old_limit);
struct rlimit {
    rlim_t rlim_cur;  /* Soft limit */
    rlim_t rlim_max;  /* Hard limit (ceiling for rlim_cur) */
};
  • 更改资源限制时,要注意:
    • 软限制值需小于或等于硬限制值
    • 可降低硬限制值,需大于等于软限制值
    • 只有超级用户可以提高硬限制值
©️2020 CSDN 皮肤主题: 黑客帝国 设计师:上身试试 返回首页