UNIX環境高階程式設計習題——第二章

Arturia發表於2019-05-13

第二章習題

2.1 在2.8節中基本資料型別可以在多個檔案中定義。例如,在FreeBSD 8.0中,size_t在29個不同的檔案中都有定義,由於一個程式可能包含這29個不同的標頭檔案,在ISO C 卻不允許對同一個名字進行多次typedef,那麼如何編寫這些標頭檔案呢?

為了避免多次包含typedef語句,我們可以使用#ifndef標識

#ifndef _MACHINE_TYPES_H_  
#define _MACHINE_TYPES_H_  
  
typedef int _int32_t;  
typedef unsigned int _uint32_t;  
  
.........  
  
typedef _uint32_t _size_t;  
  
.........  
  
#enddef

2.2 檢查系統的標頭檔案,列出基本系統資料所用到的實際資料型別
1、我所使用的為Linux系統,發行版為Fedora,基本資料型別所在標頭檔案為
/usr/include/sys/types.h

#include <bits/types.h>

#ifdef    __USE_MISC
# ifndef __u_char_defined
typedef __u_char u_char;
typedef __u_short u_short;
typedef __u_int u_int;
typedef __u_long u_long;
typedef __quad_t quad_t;
typedef __u_quad_t u_quad_t;
typedef __fsid_t fsid_t;
#  define __u_char_defined
# endif
#endif

這裡找到的仍然不是題目所要求的實際資料型別,我們便從
#include <bits/types.h>中查詢

#include <features.h>
#include <bits/wordsize.h>

/* Convenience types.  */
typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;
typedef unsigned long int __u_long;

/* Fixed-size types, underlying types depend on word size and compiler.  */
typedef signed char __int8_t;
typedef unsigned char __uint8_t;
typedef signed short int __int16_t;
typedef unsigned short int __uint16_t;
typedef signed int __int32_t;
typedef unsigned int __uint32_t;
#if __WORDSIZE == 64
typedef signed long int __int64_t;
typedef unsigned long int __uint64_t;
#else
__extension__ typedef signed long long int __int64_t;
__extension__ typedef unsigned long long int __uint64_t;
#endif

/* quad_t is also 64 bits.  */
#if __WORDSIZE == 64
typedef long int __quad_t;
typedef unsigned long int __u_quad_t;
#else
__extension__ typedef long long int __quad_t;
__extension__ typedef unsigned long long int __u_quad_t;
#endif

2.3 改寫圖2-17中的程式,使其在sysconf為OPEN_MAX限制返回LONG_MAX時,避免進行不必要的處理。
1、源程式:

/*************************************************************************
    > File Name: openmax.c
    > Author: King
    > Mail: arturiapendragon_1@163.com 
    > Created Time: 2017年05月03日 星期三 19時05分42秒
 ************************************************************************/

#include "apue.h"
#include <errno.h>
#include <limits.h>

#ifdef OPEN_MAX
static long openmax = OPEN_MAX;
#else
static long openmax = 0;
#endif 


/*
 * If OPEN_MAX is indeterminate, this might be inadequate
 */
#define OPEN_MAX_GUESS 256


long open_max(void)
{
    if (openmax ==0){    /* first time through */
        errno = 0;

    if ((openmax = sysconf(_SC_OPEN_MAX)) < 0) {
            if (errno == 0)
                openmax = OPEN_MAX_GUESS;    /* it`s indeterminate */
            else
                err_sys("sysconf error for _SC_OEPN_MAX");
        }
    }
    return(openmax);
}

int main(void)
{
    printf("%ld
",open_max());
}

執行結果為:

king at Fedora in ~/apue/chapter2 
$ gcc openmax.c 

king at Fedora in ~/apue/chapter2 
$ ./a.out 
1024

因為sysconf函式在Linux可能返回的是LONG,造成程式執行混亂:
因此,修改後的程式:

/*************************************************************************
    > File Name: openmax.c
    > Author: King
    > Mail: arturiapendragon_1@163.com 
    > Created Time: 2017年05月03日 星期三 19時05分42秒
 ************************************************************************/

#include "apue.h"
#include <errno.h>
#include <limits.h>
#include <sys/resource.h>    //為了支援getrlimit函式以及結構體rlimit的使用

#ifdef OPEN_MAX
static long openmax = OPEN_MAX;
#else
static long openmax = 0;
#endif 


/*
 * If OPEN_MAX is indeterminate, this might be inadequate
 */
#define OPEN_MAX_GUESS 256


long open_max(void)
{
    struct rlimit rl;
    if (openmax ==0){    /* first time through */
        errno = 0;

    if ((openmax = sysconf(_SC_OPEN_MAX)) < 0 || openmax==LONG_MAX) {
            if((openmax=getrlimit(RLIMIT_NOFILE,&rl))<0){
                err_sys("can not get file limit
");
            }else if(openmax==RLIM_INFINITY)
                openmax = OPEN_MAX_GUESS;
            else
                openmax=rl.rlim_max;
        }
    }
    return(openmax);
}

int main(void)
{
    printf("%ld
",open_max());
}

通過man getrlimit可檢視getrlimit函式的實現以及引數:

       The value RLIM_INFINITY denotes no limit on a resource (both in the structure returned by getrlimit() and in the structure passed to setrlimit()).

       RLIMIT_NOFILE
              Specifies  a  value  one  greater  than the maximum file descriptor number that can be opened by this process.  Attempts (open(2), pipe(2), dup(2),
              etc.)  to exceed this limit yield the error EMFILE.  (Historically, this limit was named RLIMIT_OFILE on BSD.)
       

相關文章