美文网首页
第2章——《Unix标准及实现》

第2章——《Unix标准及实现》

作者: alex_man | 来源:发表于2018-06-25 13:10 被阅读0次

    实验环境介绍

    • gcc:4.8.5
    • glibc:glibc-2.17-222.el7.x86_64
    • os:Centos7.4
    • kernel:3.10.0-693.21.1.el7.x86_64

    引言

    • 略过

    Unix标准化

    • 都是历史,略过

    Unix系统实现

    • 都是历史,略过

    标准与实现的差异

    • 略过

    限制

    unix限制
    • 必需的两种限制:
      • 编译时限制(例如:短整型的最大值)
      • 运行时限制(例如:文件名有多少字符)
    • 编译时限制的解决方案:头文件
    • 运行时限制的解决方案 :
      • 与文件和目录无关的运行时限制:sysconf函数
      • 与文件或目录有关的运行时限制:pathconf和fpathconf函数

    后面说明

    ISO C限制
    • 在limit.h中,如下图:


      <limits.h>中定义的整型大小
    • 测试代码如下:

    #include <limits.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int
    main(int argc, char *argv[])
    {
        printf("CHAR_BIT: %d\n", CHAR_BIT);
        printf("CHAR_MAX: %d\n", CHAR_MAX);
        printf("CHAR_MIN: %d\n", CHAR_MIN);
        printf("INT_MAX: %d\n", INT_MAX);
        printf("INT_MIN: %d\n", INT_MIN);
    
        exit(EXIT_SUCCESS);
    }
    
    result:
    CHAR_BIT: 8
    CHAR_MAX: 127
    CHAR_MIN: -128
    INT_MAX: 2147483647
    INT_MIN: -2147483648
    
    POSIX限制
    • posix.1定义了很多设计操作系统实现限制的常量,我们只关心与基本posix.1接口有关的部分。这些限制和常量分为下列7类:
      • 数值限制:LOG_BIT、SSIZE_MAX和WORD_BIT
      • 最小值:如下图,这些最小值并不随系统而改变。(忽略名字中的max)


        <limits.h>中的POSIX最小值
      • 最大值:_POSIX_CLOCKRES_MIN
      • 运行时可以增加的值:CHARCLASS_NAME_MAX、COLL_WEIGHTS_MAX、LINE_MAX、NGROUPS_MAX和RE_DUP_MAX
      • 运行时不变值:如下图等


        POSIX运行时不变值
        线程配置限制实例
        POSIX异步I/O运行时不变值
      • 其他不变值:NL_ARGMAX、NL_MSGMAX、NL_SSETMAX和NL_TEXTMAX
      • 路径名可变值:FILESIZEBITS、LINK_MAX、MAX_CANON、MAX_INPUT、NAME_MAX、PATH_MAX、PIPE_BUF和SYMLINK_MAX

    某些变量可能没有在<limits.h>中,所以需要使用sysconf、pathconf、fpathconf来获取

    XSI限制
    • XSI定义了代表实现限制的几个常量
      • 最小值:如下图


        XSI最小值
      • 运行时不变值(可能不确定):IOV_MAX和PAGE_SIZE
    函数sysconf、pathconf和fpathconf
    • sysconf的限制及其参数如下图


      对sysconf的限制及name参数
    • 测试代码如下

    #include <limits.h>
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    #define ONE_MB  (1024 * 1024)
    
    int
    main(int argc, char *argv[])
    {
        // test sysconf
        printf("The number of processors configured is :%ld\n",
            sysconf(_SC_NPROCESSORS_CONF));
        printf("The number of processors currently online (available) is :%ld\n",
            sysconf(_SC_NPROCESSORS_ONLN));
        printf ("The pagesize: %ld\n", sysconf(_SC_PAGESIZE));
        printf ("The number of pages: %ld\n", sysconf(_SC_PHYS_PAGES));
        printf ("The number of available pages: %ld\n", sysconf(_SC_AVPHYS_PAGES));
        printf ("The memory size: %lld MB\n",
            (long long)sysconf(_SC_PAGESIZE) * (long long)sysconf(_SC_PHYS_PAGES) / ONE_MB );
        printf ("The number of files max opened:: %ld\n", sysconf(_SC_OPEN_MAX));
        printf("The number of ticks per second: %ld\n", sysconf(_SC_CLK_TCK));
        printf ("The max length of host name: %ld\n", sysconf(_SC_HOST_NAME_MAX));
        printf ("The max length of login name: %ld\n", sysconf(_SC_LOGIN_NAME_MAX));
    
        // test
        char pathname[] = "/home";
        printf("NAME_MAX = %ld\n", pathconf(pathname, _PC_NAME_MAX));
        printf("PATH_MAX = %ld\n", pathconf(pathname, _PC_PATH_MAX));
        printf("LINK_MAX = %ld\n", pathconf(pathname, _PC_LINK_MAX));
        printf("MAX_INPUT = %ld\n", pathconf(pathname, _PC_MAX_INPUT));
        printf("MAX_CANON = %ld\n", pathconf(pathname, _PC_MAX_CANON));
        printf("PIPE_BUF = %ld\n", pathconf(pathname, _PC_PIPE_BUF));
    
        // test fpathconf
        int  files = open(pathname, O_RDONLY);
        printf("NAME_MAX = %ld\n", fpathconf(files, _PC_NAME_MAX));
        printf("PATH_MAX = %ld\n", fpathconf(files, _PC_PATH_MAX));
        printf("LINK_MAX = %ld\n", fpathconf(files, _PC_LINK_MAX));
        printf("MAX_INPUT = %ld\n", fpathconf(files, _PC_MAX_INPUT));
        printf("MAX_CANON = %ld\n", fpathconf(files, _PC_MAX_CANON));
        printf("PIPE_BUF = %ld\n", fpathconf(files, _PC_PIPE_BUF));
        exit(EXIT_SUCCESS);
    }
    
    result:
    The number of processors configured is :2
    The number of processors currently online (available) is :2
    The pagesize: 4096
    The number of pages: 249657
    The number of available pages: 35592
    The memory size: 975 MB
    The number of files max opened:: 1024
    The number of ticks per second: 100
    The max length of host name: 64
    The max length of login name: 256
    NAME_MAX = 255
    PATH_MAX = 4096
    LINK_MAX = 2147483647
    MAX_INPUT = 255
    MAX_CANON = 255
    PIPE_BUF = 4096
    NAME_MAX = 255
    PATH_MAX = 4096
    LINK_MAX = 2147483647
    MAX_INPUT = 255
    MAX_CANON = 255
    PIPE_BUF = 4096
    
    • pathconf和fpathconf的限制及name参数如下图


      pathconf和fpathconf的限制及name参数
    不确定的运行时限制
    • 前面说的某些限制值可能是不确定的。如果没有在<limits.h>中定义,那么在编译的时候就不能使用它们
    • 路径名:很多程序需要为路径名分配存储区,一般来说,在编译时就为其分配了存储区,而且不同的程序使用不同的幻数(其中很少是正确的)作为数组长度,如256、512、1024或标准I/O常量BUFSIZ。4.3BSD头文件<sys.param.h>(<font color="#dd0000">我的环境上是/usr/include/sys/param.h</font><br />)中的常量MAXPATHLEN才是正确的值,但是很多4.3BSD应用程序并未使用它。POSIX.1师徒用PATH_MAX值来获取,如果<limits.h>中定义了常量PATH_MAX,那就没有任何问题,如果未定义,则需要调用pathconf(但要注意,pathconf的返回值是基于工作目录的相对路径名的最大长度,所以指定根目录为第一个参数,并将得到的返回值加1作为结果值)
    • 测试代码如下
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <limits.h>
    #include <unistd.h>
    
    #ifdef PATH_MAX
    static long pathmax = PATH_MAX;
    #else
    static long pathmax = 0;
    #endif
    
    static long posix_version = 0;
    static long xsi_version = 0;
    
    
    #define PATH_MAX_GUESS 1024
    
    char *
    path_alloc(size_t *sizep)
    {
        char *ptr;
        size_t size;
    
        if (!posix_version)
            posix_version = sysconf(_SC_VERSION);
    
        if (!xsi_version)
            xsi_version = sysconf(_SC_XOPEN_VERSION);
    
        if (!pathmax) {
            errno = 0;
            if ((pathmax = pathconf("/", _PC_PATH_MAX)) < 0) {
                int errno_save = errno;
                if (errno_save == 0)
                    pathmax = PATH_MAX_GUESS;
                else
                    perror("pathconf error for _PC_PATH_MAX:");
            } else
                pathmax++;
        }
    
        if ((posix_version < 200112L) && (xsi_version < 4))
            size = pathmax + 1;
        else
            size = pathmax;
    
        if ((ptr = malloc(size)) == NULL)
            perror("malloc error for pathname");
    
        if (sizep)
            *sizep = size;
    
        return (ptr);
    }
    
    int
    main(int argc, char *argv[])
    {
        size_t size;
        char *ptr = path_alloc(&size);
        if (ptr)
            printf("alloc size = %zu successfully\n", size);
        else
            printf("alloc failed\n");
    
        exit(EXIT_SUCCESS);
    }
    
    result:
    [root@localhost part_2]# ./2_16 
    alloc size = 4096 successfully
    
    • 最大打开文件数:使用POSIX.1的OPEN_MAX来提高移植性
    • 测试代码如下
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <limits.h>
    #include <unistd.h>
    
    #ifdef OPEN_MAX
    static long openmax = OPEN_MAX;
    #else
    static long openmax = 0;
    #endif
    
    #define OPEN_MAX_GUESS 256
    
    long
    open_max(void)
    {
        if (!openmax) {
            errno = 0;
            if ((openmax = sysconf(_SC_OPEN_MAX)) < 0) {
                if (!errno)
                    openmax = OPEN_MAX_GUESS;
                else
                    perror("sysconf error for _SC_OPEN_MAX");
            }
        }
    
        return (openmax);
    }
    
    int
    main(int argc, char *argv[])
    {
        long openmax = open_max();
        if (openmax < 0)
            printf("open_max get error\n");
        else
            printf("openmax is: %ld\n", openmax);
        exit(EXIT_SUCCESS);
    }
    
    result:
    [root@localhost part_2]# ./2_17 
    openmax is: 1024
    

    选项

    • 如同对限制的处理一样,posix.1定义了3种处理选项的方法
      • 编译时选项定义在<unistd.h>
      • 与文件或目录无关的运行时选项用sysconf函数来判断
      • 与文件或目录有关的运行时选项通过调用pathconf或fpathconf
    • 其他的忽略

    功能测试宏

    • 忽略

    基本系统数据类型

    • 头文件中定义了某些与实现有关的数据类型。绝大多数都是以_t结尾,用这种方式定义这些数据类型后,就不再需要考虑因系统不同而变化的程序实现细节

    • 如下图


      常用基本数据类型

    标准之间的冲突

    • ISO C定义了clock函数,返回进程使用的cpu时间,返回值是clock_t类型值,单ISO C没有规定他的单位。为了将值转换成以秒为单位,需要将其除以在<time.h>中定义的CLOCKS_PER_SEC.POSIX.1定义了times函数,他返回其调用者及其所有终止子进程的cpu时间以及时钟时间。ISO C和POSIX.1用同一种数据类型(clock_t)来保存对时间的测量,但定义了不同单位,所以在使用clock_t类型变量的时候,必须小心

    • 由于ISO C函数较少考虑宿主操作系统,所以POSIX的系统为了兼容性也会实现ISO C函数,signal函数(希望编写可在ISO C环境和较早的UNIX系统中运行的可兼容程序),他和POSIX.1 sigaction函数不同。第10章再来说明

    相关文章

      网友评论

          本文标题:第2章——《Unix标准及实现》

          本文链接:https://www.haomeiwen.com/subject/fmqyyftx.html