zoukankan      html  css  js  c++  java
  • 《APUE》第七章笔记

    这一章主要是要解决这么几个问题:

    当执行程序时,main函数是如何被调用的?

    main函数的原型是:

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

    其中argc是命令个数,argv则是字符指针,指向字符串(命令)。

    当内核执行一个C程序的时候,是由一个特别的起始例程(exex函数族的一个)来调用main函数的。

    命令行参数是如何传递给执行程序的?

    当执行一个程序时,调用exec的进程可将命令行参数传递给该新程序。argc[argc]是NULL。

    典型的存储器布局是什么样式的?

    一个C程序由这么几个segment(段)组成:text segment, data segment, bss segment, stack segment, heap等。

    bss段就是用来存放全局变量等不在函数内声明的变量。(所以你定义了一个全局变量,但没有初始化,你打印出来会是等于0的。因为exec会帮你初始化为0)

    如何分配额外的存储空间?

    ISOC指定了三个用于动态分配内存的函数:

    (1)malloc,分配指定字节数的存储区。此存储区的字节的初始值不确定。

    (2)calloc,为指定数量和指定字节数的对象分配存储空间,该空间中的每一位都初始化为0。

    (3)realloc,更改以前分配区的长度(增加或减少),当增加时,则是移向一块更加的新区域,新增的部分的初始值不确定。

    #include <stdlib.h>

    void *malloc(size_t size);

    void *calloc(size_t nobj, size_t size);

    void *realloc(void *ptr, size_t newsize);

    三个函数返回值:成功返回非NULL指针,失败返回NULL指针

    void free(void *ptr);

    对于上面的这四个函数,我是对malloc和free比较熟悉。下面再说点,其实实际获得的空间会比要求的会多一些出来,多出来的会用来存储这个空间的一些参数,比如说:分配空间的大小,指向下一个分配空间的指针等等。

    所以使用这些函数一般比较多犯的两个错误是:1.像数组那样,越界,往后面写东西,这样会导致一些很严重的错误,可能下一个分配空间的指针指向的空间就找不到了。

    2.没有free调那些不用的空间,那么就会造成泄漏或者free掉一个空指针。

    这两个错误都是很难检测出来的,所以要特别小心。

    进程如何使用环境变量?

    介绍几个用于环境变量操作的函数:

    #include <stdlib.h>

    char *getenv(const char *name);

    找到则指向该环境变量的指针,否则返回NULL

    int putenv(char *str);

    int setenv(const char *name, const char *value, int rewrite);

    int unsetenv(const char *name);

    三个函数返回值:成功返回0,出错返回非0

    getenv()函数就是获得某个环境变量的值;

    putenv()取形式为name = value的,并将其放入环境表中。如果name已经存在,则先删除原来的定义字符串。

    setenv()将name设置为value。如果环境中name已经存在,则若rewrite非0,则首先删除现有的定义;若rewrite为0,则不删除现有定义(什么都不干)。

    unsetenv()则删除name的定义,即使不存在也不出错。

    各种不同的进程终止方式(因为现在还不太懂,所以也只是简单的说一下)

    有8种方式使进程终止,其中5种是正常终止

    1.从main返回

    2.调用exit

    3.调用_exit或_Exit

    4.最后一个线程从其启动例程返回

    5.最后一个线程调用pthread_exit

    异常终止有3种方式

    6.调用abort

    7.接到一个信号并终止

    8.最后一个县城对取消请求作出响应

    longjmp和setjmp函数以及它们和栈的交互作用

    我们都知道,栈是保存用来保存函数的一些信息的,以便返回时能够找到之前的那个函数。比如这么一个例子,main函数里调用do_line函数,do_line函数里调用cmd_add函数,则当调用到cmd_add函数时,栈是这样的:

    要是在cmd里遇到错误,想返回到main函数时怎么办?那就要用到setjmp函数和longjmp函数了。

    #include <setjmp.h>

    int setjmp(jmp_buf env);

    返回值:直接调用返回0,否则就返回longjmp的val值

    void longjmp(jmp_buf env, int val);

    简单来说,在嵌套调用的函数中,如果遇到了longjmp函数,则会马上返回到调用setjmp函数的那个函数。比如说我在cmd_add函中调用了longjmp函数,在main函数中设置setjmp函数。当我在cmd_add函数中因为错误而触发到longjmp函数,那么就会马上返回到具有setjmp函数的main函数了。当返回去了,而在栈里各个函数的变量的值会变得怎样呢?

    下面给出例子:

     1 #include "apue.h"
     2 #include <setjmp.h>
     3 
     4 static void f1(int, int, int, int);
     5 static void f2(void);
     6 
     7 static jmp_buf    jmpbuffer;
     8 static int    globval;
     9 
    10 int main(void)
    11 {
    12     int        autoval;
    13     register int    regival;
    14     volatile int    volaval;
    15     static int    statval;
    16 
    17     globval = 1;
    18     autoval = 2;
    19     regival = 3;
    20     volaval = 4;
    21     statval = 5;
    22 
    23     if (setjmp(jmpbuffer) != 0)
    24     {
    25         printf("after longjmp
    ");
    26         printf("globval = %d, autoval = %d, regival = %d, volaval = %d, statval = %d
    ",
    27                 globval, autoval, regival, volaval, statval);
    28         exit(0);
    29     }
    30 
    31     /*
    32      * Change variables after setjmp, but before longjmp.
    33      */
    34     globval = 95;
    35     autoval = 96;
    36     regival = 97;
    37     volaval = 98;
    38     statval = 99;
    39 
    40     f1(autoval, regival, volaval, statval);    /* never return */
    41     exit(0);
    42 
    43 }
    44 
    45 static void f1(int i, int j, int k, int l)
    46 {
    47     printf("in f1():
    ");
    48     printf("globval = %d, autoval = %d, regival = %d, volaval = %d, statval = %d
    ",
    49             globval, i, j, k, l);
    50     f2();
    51 }
    52 
    53 static void f2()
    54 {
    55     longjmp(jmpbuffer, 1);
    56 }
    View Code

    书上说这变量变不变是看情况,你可以在你自己的电脑上试一试。

  • 相关阅读:
    StringBuild
    String 字符串
    win7 64位支持的最大内存
    Spring获取对象与java new对象区别
    生成随机数
    java String转base64
    java时间格式
    Bash Scripting Learn Notes
    Linux parent process and child process when 'sudo'
    Linux services, runlevels, and rc.d scripts
  • 原文地址:https://www.cnblogs.com/fusae-blog/p/4285953.html
Copyright © 2011-2022 走看看