[转]C程序运行、退出过程及内存分配

英文文献地址:http://book.chinaunix.net/special/ebook/addisonWesley/APUE2/0201433079/ch07lev1sec3.html#ch07fig01
1、内核执行C程序(用exec)
   在调用main函数之前会调用一个特殊的启动程序
   它从内核中获取 命令行参数和环境变量 供main函数使用
   可执行程序以它作为程序的开始地址
2、C程序的开始和结束
Fig.1 How a C program is started and how it terminate
注1:#include <stdlib.c>
    void exit(int statues);
    void _Exit(int statues);
    #include <unistd.h>
    void _exit(int status);
    后2个函数立即返回内核
    第1个函数首先执行exit handlers,执行flush buffer(all buffered datas be flushed),关掉标准IO库,用fclose关掉所有打开的streams
注2:exit(0) 等同于 return(0)
注3: #include <stdlib.h>
     int atexit(void (*func)(void));
     (用于注册exit handlers)
注4:除了exit系列函数,还有信号可以终止进程

3、命令行参数 和 环境变量
   for(i = 0; i <argc; i++)
   ISO C和POSIX.1都确保argv[argc]是NULL,所以
   for(i = 0; argv[i] != NULL; i++)

   extern char **environ;(字符串数组)
   i.e: HOME=/home/sar/0
        PATH=:/bin:/usr/bin/0
        SHELL=/bin/bash/0
        USER=sar/0
        LOGNAME=sar/0
   最早的时候写成
   int main(int argc, char *argv[], char *envp[])
   但POSIX.1规定最后一个变量用getenv系列函数来操作
   #include <stdlib.h>
   int putenv(char *str);
   int setenv(const char *name, const *value, int
              rewrite);
   int unsetenv(const char *name);

4、C程序内存布局
Fig.2 Typical memory arrangement
注1:.text----CPU执行的机器指令,只读,共享(任何C程序可用)
     .data----初始化的数据
     .bss----"block started by symbol"(古老的汇编运算符)C declaration
    
注2:LINUX intel x86下,.text起始于0x08048000,stack底低于
     0xC0000000

注3:只有.text 和.data 需要存储,而.bss在程序开始运行之前全部被设置为
     0或者NULL

注4:可以用size命令查看各部分大小
     $size /usr/sh

注5:一般以静态方式进行编译的可执行文件通常会很大,那是因为以普通方
    式(共享库模式)编译,共享库从可执行文件移出了通用库routines,而
    通过在内存中为所有程序维持一份拷贝作为参考

5、内存分配
   #include <stlib.h>
   void *malloc(size_t size);
   void *calloc(size_t nobj, size_t size);
   // a specified number of objects of a specified size,i
   // initialzied to all 0 bits
   void *realloc(void *ptr, size_t newsize);
   // increases or decreases the size of a previously allocated area
   void free(void *ptr);
注1: 分配的内存都被确保很好的aligned
注2: 它们一般都是通过sbrk()系统调用来实现
注3: 通常分配的内存比程序的指定要大点,因为需要一些附加的空间来记录
      分配块的打消,下一个分配块的指针等等。所以写这一部分是件不允许
      的事情
注4: 忘记free,那么只要程序在运行,进程内存的使用就会持续增加直到
      无内存可用,这叫leakage

6、setjmp和longjmp(跨越函数的跳跃)
   #include <setjmp.h>
   int setjmp(jmp_buf env);
   void longjmp(jmp_buf env, int val);

注1:jmp_buf----数组形式,保存所有需要的信息存储到stack直到调用
     longjmp
     val----非0,作为从setjmp的返回值
     if (setjmp(jmbbuffer) != 0)
     ...
     longjmp(jmpbuffer, 1);
注2:这两个函数在编译优化的时候并不影响globlal,static和volatile变量
     但是影响automatic和register变量。因为在CPU里的变量和浮点寄存器
     在setjmp调用时就已经存储好了,其他存储在内存的变量与longjmp时的
     值一样

7、getrlimit和setrlimit(获取和设置系统资源限制)
   #include <sys/resource.h>
   int getrlimit(int resource, struct rlimit *rlptr);
   int setrlimit(int resource, const struct rlimit *rlptr);
   (0 if OK, nonzero on error)
注1:系统资源----比如data段的大小,程序使用的最大空间等等
注2:resource limits影响调用进程和子进程
     resource limits可以设置到shell影响所有进程(ulimit命令)
转自: http://blogold.chinaunix.net/u3/99982/showart_2053197.html
该人的博客里,还有不少关于算法的,例如图,希尔排序等算法。

你可能感兴趣的:(c,算法,struct,shell,null,存储)