Chinaunix首页 | 论坛 | 博客
  • 博客访问: 316758
  • 博文数量: 79
  • 博客积分: 1480
  • 博客等级: 上尉
  • 技术积分: 848
  • 用 户 组: 普通用户
  • 注册时间: 2009-06-11 15:29
文章分类

全部博文(79)

文章存档

2012年(1)

2011年(5)

2010年(19)

2009年(54)

我的朋友

分类: C/C++

2009-09-14 14:01:35

1、内核执行C程序(用exec)
   在调用main函数之前会调用一个特殊的启动程序
   它从内核中获取 命令行参数和环境变量 供main函数使用
   可执行程序以它作为程序的开始地址
2、C程序的开始和结束
Fig.1 How a C program is started and how it terminate
注1:#include
    void exit(int statues);
    void _Exit(int statues);
    #include
    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
     int atexit(void (*func)(void));
     (用于注册exit handlers)
注4:除了exit系列函数,还有信号可以终止进程

3、命令行参数 和 环境变量
   for(i = 0; 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
   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
   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
   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
   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命令)

阅读(1061) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~