Nathaniel's blog
Back to posts

APUE reading notes-2

Nathaniel LinAugust 15, 20173 min read6 views
APUE reading notes-2

第二章

  1. 2.1

We mentioned in Section 2.8 that some of the primitive system data types are defined in more than one header. For example, in FreeBSD 8.0, size_t is defined in 29 different headers. Because all 29 headers could be included in a program and because ISO C does not allow multiple typedefs for the same name, how must the headers be written?

个人认为,遇到这种情况时,假设多重定义的类型为#size_t,那么可以采用include guard的策略,即在头文件中,声明size_t时,进行一次#ifndef#endif的保护,从而可以避免size_t的多重定义。

  1. 2.2

Examine your system’s headers and list the actual data types used to implement the primitive system data types.

我的系统是macOS 10.12.6,也算是认证的Unix系统了,于是在对<sys/types.h>进行暗中观察😏之后,得出结论如下:


typedef	unsigned char		u_char;

typedef	unsigned short		u_short;

typedef	unsigned int		u_int;

#ifndef _U_LONG

typedef	unsigned long		u_long;

#define _U_LONG

#endif

typedef	unsigned short		ushort;		/* Sys V compatibility */

typedef	unsigned int		uint;		/* Sys V compatibility */

#endif

typedef	u_int64_t		u_quad_t;	/* quads */

typedef	int64_t			quad_t;

typedef	quad_t *		qaddr_t;

typedef	char *			caddr_t;	/* core address */

typedef	int32_t			daddr_t;	/* disk address */

typedef	u_int32_t		fixpt_t;	/* fixed point number */

typedef	int32_t			segsz_t;	/* segment size */

typedef	int32_t			swblk_t;	/* swap offset */

typedef __int32_t		fd_mask;

这里仅仅列出了一些基本数据类型的实现,在sys/_types文件夹下的头文件中还有许多的其他的常见类型,如size_ttime_t等的实现,再此由于篇幅有限就不予详述了,总体而言,Unix下的不少以_t结尾的类型,都是随各个系统的实现方式而可能发生变化的,具体的实现只要观察<sys/types.h>即可得知。这个信息可以帮助我们解决一些潜在的bug。

简单的介绍一些常见的unix定义的变量类型:

| 名称

| 表示数据

| | ------------ | ------------------------------------------------------------ | | clock_t

| CPU时钟周期

| | comp_t

| 压缩后的CPU时钟周期(不属于POSIX标准)

| | dev_t

| 设备编号

| | fd_set

| 文件描述符集合

| | fpos_t

| 文件位置

| | gid_t

| 用户组ID

| | ino_t

| inode值(inode为一种文件系统对象,用于区分文件和文件夹等文件类型) | | mode_t

| 文件类型、文件权限

| | nlink_t

| 该目录的链接数

| | off_t

| 文件大小和偏移量

| | pid_t

| 进程ID和进程组ID

| | pthread_t

| 线程ID

| | ptrdiff_t

| 两个指针相减的结果

| | rlim_t

| 资源上限

| | sig_atomic_t | 可用作信号量的原子数据类型

| | sigset_t

| 信号量集合

| | size_t

| 对象的大小(非负)

| | ssize_t

| 对象的大小或-1

| | time_t

| 日历时间单位

| | uid_t

| 用户ID

| | wchar_t

| 宽字符

|

  1. 2.3

Update the program in Figure 2.17 to avoid the needless processing that occurs when sysconf returns LONG_MAX as the limit for OPEN_MAX.

Fig 2.17内容如下:


#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) {

errno = 0;

/* first time through */

if ((openmax = sysconf(_SC_OPEN_MAX)) < 0) {

if (errno == 0)

openmax = OPEN_MAX_GUESS;

/* it’s indeterminate */

else

fprintf(stderr, "sysconf error for _SC_OPEN_MAX");

}

}

return(openmax);

}

由于实在没读懂题意,我去Google了一下,获得了如下的答案:


#include "apue.h"

#include <limits.h>

#include <sys/resource.h>

#define OPEN_MAX_GUESS 256

long

open_max(void)

{

   long openmax;

   struct rlimit rl;

   if ((openmax = sysconf(_SC_OPEN_MAX)) < 0 ||

   	 openmax == LONG_MAX) {

   	if (getrlimit(RLIMIT_NOFILE, &rl) < 0)

   		err_sys("can't get file limit");

   	if (rl.rlim_max == RLIM_INFINITY)

   		openmax = OPEN_MAX_GUESS;

   	else

   		openmax = rl.rlim_max;

   }

   return(openmax);

}

简单的来说,如果sysconf函数返回了LONG_MAX,那么这也表明OPEN_MAX是不确定的,同时,我们可以使用geTRlimit函数来获得每个进程最大的同时打开文件数量,从而使OPEN_MAX成为一个合理的上限值。

Share this post

Reactions