• apue2阅读笔记 第6.7章


    这两章的内容相对较少,所以合到一起写。

    第六章

    1. 获取pwd结构体指针的三个函数:

    #include <pwd.h>
    struct passwd *getpwuid(uid_t uid);
    struct passwd *getpwnam(const char *name);

    struct passwd *getpwent(void);

    2. 其他数据文件

    Description  Data file        Header   Structure functions

    passwords  /etc/passwd <pwd.h> passwd   getpwnam, getpwuid

    groups       /etc/group  <grp.h> group    getgrnam, getgrgid

    shadow      /etc/shadow <shadow.h> spwd  getspnam

    hosts /etc/hosts <netdb.h> hostent gethostbyname, gethostbyaddr

    networks /etc/networks <netdb.h> netent getnetbyname, getnetbyaddr

    protocols /etc/protocols <netdb.h> protoent getprotobyname, getprotobynumber

    services /etc/services <netdb.h> servent getservbyname, getservbyport

    3. 系统时间

    (1)两个获取时间的函数

    A:

    #include <time.h>
    time_t time(time_t *calptr);

    #include <sys/time.h>
    int gettimeofday(struct timeval *restrict tp, void *restrict tzp);

    struct timeval {
               time_t tv_sec;    /* seconds */
               long   tv_usec;   /* microseconds */
       };

    注意timeval可以精确到us级别。

    (2)

    image

    第七章

    1. 基本知识

    7.2   main函数
    C程序总是从m a i n函数开始执行。m a i n函数的原型是:
    int main(int a rg c, char *a rg v[ ] ) ;
    其中,a rg c是命令行参数的数目,a rg v是指向参数的各个指针所构成的数组。7 . 4节将对命令行
    参数进行说明。
    当内核起动C程序时(使用一个e x e c函数,8 . 9节将说明e x e c函数),在调用m a i n前先调用一个特殊的起动例程。可执行程序文件将此起动例程指定为程序的起始地址——这是由连接编辑程序设置的,而连接编辑程序则由 C编译程序(通常是c c )调用。起动例程从内核取得命令行参数和环境变量值,然后为调用m a i n函数作好安排。
    7.3   进程终止
    有五种方式使进程终止:
    (1) 正常终止:
    (a) 从m a i n返回。
    (b) 调用e x i t。
    (c) 调用_ e x i t。
    (2) 异常终止:
    (a) 调用a b o r t (见第1 0章)。
    (b) 由一个信号终止(见第1 0章)。
    上节提及的起动例程是这样编写的,使得从 m a i n返回后立即调用e x i t函数。如果将起动例
    程以C代码形式表示(实际上该例程常常用汇编语言编写),则它调用m a i n函数的形式可能是:
    exit( main(argc, argv) );
    7.3.1   exit和_ e x i t函数
    e x i t和_ e x i t函数用于正常终止一个程序: _ e x i t立即进入内核,e x i t则先执行一些清除处理
    (包括调用执行各终止处理程序,关闭所有标准I / O流等),然后进入内核。

    关于atexit 函数

    With ISO C, a process can register up to 32 functions that are automatically called by exit. These are called exit handlers and are registered by calling the atexit function.

    #include <stdlib.h>
    int atexit(void (*func)(void));

    Returns: 0 if OK, nonzero on error

    image

    注意,内核使程序执行的唯一方法是调用一个 e x e c函数。进程自愿终止的唯一方法是显式或隐式地(调用e x i t )调用_ e x i t。进程也可非自愿地由一个信号使其终止(图7 - 1中没有显示)。

    2.

    We are guaranteed by both ISO C and POSIX.1 that argv[argc] is a null pointer. This lets us alternatively code the argument-processing loop as

    for (i = 0; argv[i] != NULL; i++) //最后一个是空指针

    同理,每个程序都接收到一张环境表。与参数表一样,环境表也是一个字符指针数组,其中每个指针包含一个以n u l l结束的字符串的地址。全局变量e n v i r o n则包含了该指针数组的地址。
    extern char **environ;

    image


    3.

    由于历史原因,一个应用程序在内存中的布局一般分为:代码段,初始化数据段,未初始化数据段,堆,栈等几个段。

    image

    三个分配内存的函数:

    #include <stdlib.h>
    void *malloc(size_ts i z e) ;
    void *calloc(size_tn o b j, size_t s i z e) ;
    void *realloc(void * p t r, size_t n e w s i z e) ;
    三个函数返回:若成功则为非空指针,若出错则为 N U L L
    void free(void *p t r)

    另外,还有一个alloca

    #include <alloca.h>

    void *alloca(size_t size);

    这个函数分配的内存在栈上。其优点是:当函数返回时,自动释放它所使用的栈帧,所以不必再为释放空间而费心。其缺点是:某些系统在函数已被调用后不能增加栈帧长度,于是也就不能支持a l l o c a函数。

    4.

    取得环境变量的函数:

    #include <stdlib.h>
    char *getenv(const char * n a m e) ;
    返回:指向与n a m e关联的v a l u e的指针,若未找到则为N U L L

    5

    用于出错处理的setjmp 和 longjmp, 也可以考虑用goto,必须非常小心。

    #include <setjmp.h>

    void longjmp(jmp_buf env, int val);

    void siglongjmp(sigjmp_buf env, int val);

    以下摘自manual

    longjmp()  and  setjmp(3)  are  useful  for  dealing  with errors and interrupts encountered in a low-level subroutine of  a  program.   longjmp()  restores  the environment saved by the last call of setjmp(3) with the corresponding env argument.  After longjmp() is completed, program execution continues as if the  corresponding  call of setjmp(3) had just returned the value val.  longjmp() cannot cause 0 to be returned.  If longjmp() is invoked with a second argument of 0,  1 will be returned instead.

    6.

    再来个返回局部变量的改错小例子:

    #include    <stdio.h>
    
    #define DATAFILE    "datafile"
    
    FILE *
    open_data(void)
    {
        FILE    *fp;
        char    databuf[BUFSIZ];   /* setvbuf makes this the stdio buffer */
    
        if ((fp = fopen(DATAFILE, "r")) == NULL)
            return(NULL);
        if (setvbuf(fp, databuf, _IOLBF, BUFSIZ) != 0)
            return(NULL);
        return(fp);     /* error */
    }
    

    应当使用全局变量或者动态分配的变量。

  • 相关阅读:
    PIL PNG格式通道问题的解决方法
    opencv-python 学习初探2 去图片水印
    Appium、selenium与Robot Framework
    性能监控0
    XML
    Python3 读取和写入excel
    Python识别字符型图片验证码
    python进程、线程、协程
    算法和程序
    Zigbee
  • 原文地址:https://www.cnblogs.com/liujiahi/p/2259331.html
Copyright © 2020-2023  润新知