main
int main(int argc,char **argv);
//或者
int main(int argc,char *argv[]);
具体参数描述看:
关于int main( int argc, char* argv[] ) 中arg和argv参数理解
进程终止
-
正常终止
- 从main函数返回
- 调用exit
- 调用_exit或_exit
- 最后一个线程从其启动例程返回
- 从最后一个线程调用pthread_exit
-
异常终止
- 调用abort
- 接收到一个信号
- 最后一个线程对取消请求做出响应
退出函数,_exit和_Exit立即进入内核,exit则先执行一些清理处理,然后返回内核
#include <stdlib.h>
void exit(int status);
void _Exit(int status);
#include <unistd.h>
void _exit(int status);
-
status是退出状态,或者终止状态
-
exit总是执行IO库的清理关闭操作,对于所有打开的流调用fclose函数,缓冲的数据都将被冲洗
-
在main函数返回一个整型值与用该值调用exit是等价的,即exit(0)等价return(0)
函数atexit
ISO C规定一个进程可以登记多至(这里是多至不是最多,一定要注意其词语含义),这些函数由exit自动调用。我们称这些函数为终止处理程序,并调用atexit函数来登记这写函数
#include <stdlib.h>
int atexit(void (*func)(void));//成功返回0,出错返回非0
- 同一函数如若登记多次,也会被调用多次
- 以出栈的方式去调用
ISO C与POSIX.1的规定:exit首先调用各终止处理程序,然后关闭(通过fclose)所有打开流
一个C程序的运作如下图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IRaXhyqh-1639980979216)(https://raw.githubusercontent.com/dwnb/Picture/master/20211220105535.png)]
命令行参数
具体参数描述看:
关于int main( int argc, char* argv[] ) 中arg和argv参数理解
环境表
- 每个程序都收到一个环境表
环境表是一个字符指针数组
- 每个指针包含一个以null结束的c字符串地址
全局变量environ则包含了该指针数组地址,environ为环境指针,指针数组为环境表
extern char **environ
环境由name(名)=value(值)
C程序存储空间布局
C程序由以下几个部分组成
-
正文段。cpu执行机器指令的部分。通常正文段可共享的。所以即使频繁执行的程序在存储器中也只有一个副本,正文段常常是制度的,以防意外而修改其指令
-
初始化数据段。通常将此段称为数据段,它包含了程序中需要明确的赋初值的变量,例如;全局变量的赋初值
-
未初始化数据段
-
栈,自动变量以及每次函数调用时所需的保存信息都存放此段中。每次函数返回时,其返回地址及调用者环境信息都存放在栈中。
-
堆。通常在对中进行的是动态存储分配,堆位于未初始化数据段和栈之间
典型存储空间安排如下
- 未初始化数据段内容不存放在磁盘里,内核在程序运行前将他们都设置未0
共享库
具体可以参考
Linux 静态库和动态库
- 静态链接编译时加static关键字
- 动态链接加-l 后跟库
存储空间分配
3个用于存储空间动态分配的函数
#include <stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nobj,size_t size);
void *realloc(void *ptr,size_t newsize);
//3个函数返回值:若成功返回空指针,出错返回NULL
void free(void *ptr);//释放内存
- malloc,分配指定字节数存储区。
此存储区的初始值不确定
- calloc,为指定数量指定长度的对象分配存储空间。
该空间中的每一位(bit)都初始化为0
- realloc,增加或减少以前分配区的长度。
增加长度时可能需要将以前分配区的内容转移到另一个足够大的分配区,以便在尾端提供增加存储区,新增区域内初始值不确定
- 3个分配函数指针适当对齐,使其可用于任何数据对象。
例如:如果在一个特定的系统上,最苛刻的对其要求是double必须在8的倍数地址单元处开始,3个返回指针都必须这样对齐
- 3个返回值为泛化指针void *
- free释放ptr指向的空间,被释放空间的进入储区池,供以后分配
realloc的第2个参数是新空间的长度,不是新旧之差,ptr为null时,功能与malloc相同
- 这些分配通常用sbrk系统调用实现
环境变量
获取环境变量,
注意环境变量格式:name(名)=value(值)
#include <stdlib.h>
char *getenv(const char *name);//返回指向name关联的value指针,未找到返回null
- 返回指向name关联的value指针,使用getenv获取的时一个指定变量的值
#include <stdlib.h>
int putenv(char *str);//成功0,出错非0
int setenv(const char *name,const char *value,int rewrite);
int unsetenv(const char *name);
//成功0,出错-1
- putenv取形式为name=value的字符串,放入环境表,name存在则先删除原来定义
- setenv将name设置为value。若已存在rewrite非0,删除现有定义替换为rewrite,若为0,则不替换也出错
- unsetenv删除name定义,即使不存在这种定义也不算出错
函数setjmp和longjmp
跨越函数跳转功能的函数
函数getrlimit和setrlimit
进程资源限制查询和更改
参考
《APUE》
Linux 静态库和动态库