apue讀書筆記【四】:系統的限制

        UNIX系統實現定義了很多幻數和常量,其中有很多已被硬編碼進程序中,或用特定的技術確定。由於大量標準化工作的努力,已有若干種可移植的方法用以確定這些幻數和實現定義的限制。這非常有助於軟件的可移值性。

        以下兩種類型的限制是必需的:

           (1)編譯時限制(例如:智整型的最大值是什麼 ?)

           (2)運行時限制(例如:文件名可以有多少個字符?)

       編譯時限制可在頭文件中定義,程序在編譯時可以包含這些頭文件。但是,運行時限制則要求進程調用一個函數以獲得些種限制值。

       由於各種unix系統的限制不盡相同,我們需要獲得這些限制。方式有三種:

          (1)編 譯時限制(頭文件)

          (2)不與文件或目錄相關聯的運行時限制(sysconf函數)

          (3)與文件或目錄相關聯的運行時限制(pathconf和fpathconf函數)

        使事情變得複雜的是,如果一個特定的運行時限制在一個給定的系統並不改變,則可將其靜態地定義在一個頭文件中。但是,如果沒有將其定義在頭文件中,則應用程序就必須調用三個conf 函數中的一個,以確定其運行時的值。


頭文件:

     #include<unistd.h>

函數原型:

long sysconf(int name); 

long pathconf(const char *pathname, int name); 

long fpathname(int filedes, int name); 

我們需要更詳細地說明這三個函數的不同返回值。

(1)如果name不是一個合適的常量,則所有這三個函數都會返回-1,並將errno設置爲EINVAL

(2)有些nam可以返回變量的值(返回值>=0),或者返回-1,這表示該值是不確定的,此時並不改變errno的值。

demo :

#include <errno.h>
#include <unistd.h>  /*for sysconf pathconf  _SC_OPEN_MAX*/
#include <stdio.h>   /*for printf*/
#include <stdarg.h>  /*for va_list*/
#include <string.h>  /*for strcat strlen */
#include <stdlib.h>  /*for strcat exit */

#define	MAXLINE	4096			/* max line length */

static void	pr_sysconf(char *, int);
static void	pr_pathconf(char *, char *, int);
void err_quit(const char *fmt, ...);
void err_sys(const char *fmt, ...);
void err_doit(int errnoflag, int error, const char *fmt, va_list ap);


int main(int argc, char *argv[])
{
	if (argc != 2)
		err_quit("usage: a.out <dirname>");

	pr_sysconf("ARG_MAX            =", _SC_ARG_MAX);
	pr_sysconf("CHILD_MAX          =", _SC_CHILD_MAX);
	pr_sysconf("clock ticks/second =", _SC_CLK_TCK);
	pr_sysconf("NGROUPS_MAX        =", _SC_NGROUPS_MAX);
	pr_sysconf("OPEN_MAX           =", _SC_OPEN_MAX);
#ifdef	_SC_STREAM_MAX
	pr_sysconf("STREAM_MAX         =", _SC_STREAM_MAX);
#endif
#ifdef	_SC_TZNAME_MAX
	pr_sysconf("TZNAME_MAX         =", _SC_TZNAME_MAX);
#endif
	pr_sysconf("_POSIX_JOB_CONTROL =", _SC_JOB_CONTROL);
	pr_sysconf("_POSIX_SAVED_IDS   =", _SC_SAVED_IDS);
	pr_sysconf("_POSIX_VERSION     =", _SC_VERSION);
	pr_pathconf("MAX_CANON       =", "/dev/tty", _PC_MAX_CANON);
	pr_pathconf("MAX_INPUT       =", "/dev/tty", _PC_MAX_INPUT);
	pr_pathconf("_POSIX_VDISABLE =", "/dev/tty", _PC_VDISABLE);
	pr_pathconf("LINK_MAX        =", argv[1], _PC_LINK_MAX);
	pr_pathconf("NAME_MAX        =", argv[1], _PC_NAME_MAX);
	pr_pathconf("PATH_MAX        =", argv[1], _PC_PATH_MAX);
	pr_pathconf("PIPE_BUF        =", argv[1], _PC_PIPE_BUF);
	pr_pathconf("_POSIX_NO_TRUNC =", argv[1], _PC_NO_TRUNC);
	pr_pathconf("_POSIX_CHOWN_RESTRICTED =",
							argv[1], _PC_CHOWN_RESTRICTED);
	return 0;
}

static void
pr_sysconf(char *mesg, int name)
{
	long	val;

	fputs(mesg, stdout);//輸出第一個傳數的字符串
	errno = 0;
	if ( (val = sysconf(name)) < 0) {//name不是一個合適的常量,name不存在
		if (errno != 0)
			err_sys("sysconf error");
		fputs(" (not defined)\n", stdout);
	} else
		printf(" %ld\n", val);
}

static void
pr_pathconf(char *mesg, char *path, int name)
{
	long	val;

	fputs(mesg, stdout);
	errno = 0;
	if ( (val = pathconf(path, name)) < 0) {
		if (errno != 0)
			err_sys("pathconf error, path = %s", path);
		fputs(" (no limit)\n", stdout);
	} else
		printf(" %ld\n", val);
}


void err_quit(const char *fmt, ...)
{
	va_list		ap;

	va_start(ap, fmt);
	err_doit(0, 0, fmt, ap);
	va_end(ap);
	exit(1);
}

/*
 * Print a message and return to caller.
 * Caller specifies "errnoflag".
 */
void err_doit(int errnoflag, int error, const char *fmt, va_list ap)
{
	char buf[MAXLINE];

	vsnprintf(buf, MAXLINE, fmt, ap);//把格式化的輸出字符串生成
	if (errnoflag)
		snprintf(buf+strlen(buf), MAXLINE-strlen(buf), ": %s",strerror(error));//把錯誤翻譯成描述信息
	strcat(buf, "\n");//加一個換行符
	fflush(stdout);//沖洗標準輸出的緩存區
	fputs(buf, stderr);//把錯誤信息輸出到標準錯誤流
	fflush(NULL);//沖洗所有輸出流
}


/*
 * Fatal error related to a system call.
 * Print a message and terminate.
 */
void err_sys(const char *fmt, ...)
{
	va_list		ap;

	va_start(ap, fmt);
	err_doit(1, errno, fmt, ap);
	va_end(ap);
	exit(1);
}

輸出:

       





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章