UNIX环境高级编程读书笔记-七

本章主要介绍进程的环境

函数执行时, main函数是如何被调用的,命令行参数是如何传递给新程序, 典型的存储空间布局, 如何分配额外的存储空间, 进程如何使用环境变量, 进程的各种不同的终止方式, 另外学习 longjumpsetjump和栈的交互.

进程环境

本章主要介绍进程的环境

函数执行时, main函数是如何被调用的,命令行参数是如何传递给新程序, 典型的存储空间布局, 如何分配额外的存储空间, 进程如何使用环境变量, 进程的各种不同的终止方式, 另外学习 longjumpsetjump和栈的交互.

mian函数

1
int main(int argc, char * argv[]);

当内核执行C程序时, 使用一个exec函数, 在调用一个特殊的启动例程,后调用 main 函数. 可执行程序文件将此启动例程指定为程序的起始地址– 连接编辑器 设置的.

启动例程从内核中获得命令行参数和环境变量. 然后按上述方式调用main函数

进程的终止

8种termination的方式.

todo 图片

退出函数

1
2
3
4
5
6
#include <stdlib.h>
void exit(int status); // 执行关闭操作
// 直接退出
void _Exit(int status);
#include <unistd.h>
void _exit(int status);

atexit 退出函数注册函数

1
2
3
#inclde<stdlib.h>
int atexit(void (*func)(void));
//成功返回0, 失败返回非0

调用顺序与登记顺序相反

最多32个

如果缓冲区种还有数据, 调用exit,如果是行缓冲的数据,可能打印不出来, 就直接exit掉.

stdout是行缓冲的, 记得\n

命令行参数

1
2
argv
argc

环境表

环境指针, 环境字符串

C 程序的存储空间布局

正文

初始化数据

int maxcount = 1000;

未初始化数据

long sum[100];

size 命令

报告

1
2
3
➜  chap7 size /usr/bin/zsh
text data bss dec hex filename
826202 29208 79464 934874 e43da /usr/bin/zsh

共享库

1
2
3
4
5
6
➜  chap7 gcc atexit_test.c -g -o o.atexit
➜ chap7 gcc atexit_test.c -g -static -o s.o.atexit
➜ chap7 size *.atexit
text data bss dec hex filename
1964 612 4 2580 a14 o.atexit
660246 21020 6144 687410 a7d32 s.o.atexit

符号链接不影响上述段的大小,因为上述段在内存中

1
2
3
4
5
6
➜  chap7 gcc atexit_test.c  -o s.no.atexit
➜ chap7 size *.atexit
text data bss dec hex filename
1964 612 4 2580 a14 o.atexit
1964 612 4 2580 a14 s.no.atexit
660246 21020 6144 687410 a7d32 s.o.atexit

存储空间的分配

1
2
3
4
5
6
#include <stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nobj, size_t size);
void *realloc(void *ptr, size_ newsize);
// 成功返回非空指针
void free(void *ptr);

malloc

返回的指针是适当对齐的

calloc

为指定数量指定长度的对象分配存储空间.

realloc

可能会移动分区.

记得free

环境变量

1
2
3
#include<stdlib.h>
char *getenv(const char *name);
// 指向与name 关联的value的指针, 若未找到, 返回 NULL

用户可以改环境变量但是,只对自己有用.

除非

1
2
3
4
int putenv(char *str);
// 函数的返回值,若成功则返回0,失败返回非零
int setenv(const char * name. const char * value, int rewrite);
int unsetenv(const char *name);

环境字符串存在与存储空间顶部, 栈之上..

环境字符串修改起来很麻烦

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
➜  chap7 cat env.c
#include<stdlib.h>
#include<stdio.h>

int main(){
char *pchar;
pchar = getenv("HOME");
pchar [2] = 'p';

pchar [11] = 'o';
puts(getenv("HOME"));
return 0;
}
➜ chap7 ./o.env
/hpme/toadsoPATH=/home/toads/.autojump/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl

函数 setjmp和longjmp

setjmplongjmp 可以跨越函数

比较复杂, 挖坑,待填

函数 getrlimit 和 setrlimit

习题

7.1

如果未执行return或exit . 返回值未定义

7.2

stdout 采用行缓冲, 在遇到\n或者强制 fflush 或者调用exit 正常退出的情况下, 会真正输出.

7.3 ? longjump?