在编程时,很多情况需要依据系统而定,如果系统不支持 或者未定义 需要自身去定义的话
这就称之为限制,限制分两种:
1.编译时限制 这种限制可以在头文件内定义
2.运行时限制 这种情况很大程度上由系统决定所以就需要能判断系统情况的函数来帮助我们 当遇到这种限制的时候该如何去做。
POSIX规定了各种操作系统实现必须支持的各种限制的最小值,但是怎样才能找到一个特定系统实际支持的限制呢?
POSIX决定提供三个运行时确定函数以供调用:sysconf,pathconf,fpathconf,用它们可以在运行时得到实际值。
<span style="font-size:14px;">#include <unistd.h>
long sysconf(int name);
long pathconf(const char *pathname, int name);
long fpathname(int filedes, int name);
所有函数返回值:若成功则返回相应值;若出错则返回-1.</span>
这三个函数是用来求一些限制的,unix中有以下三种限制:
(1)编译时限制(头文件)
(2)不与文件或目录相关联的运行时限制(sysconf函数)
(3)与文件或目录相关联的运行时限制(pathconf函数和fpahtconf函数)
其中最后面的两个函数的区别是,一个使用路径名作为参数 ,另一个则取文件描述符作为参数。
使用一种技术:
如果系统确定了值(编译时和运行时),那么毫无疑问,使用系统提供的值;如果系统没提供,那么只有用臆测值,虽然这种技术并不能保证所有情况代码都能完美工作,但依然是我们可选择技术中最好多技术了.
编写一个程序使用以上方法:
#include<stdio.h>
#include<errno.h>
#include<limits.h>
#include<unistd.h>
int main(int argc, char *argv[])
{
//test arguments lenght.
#ifdef ARG_MAX
printf("ARG_MAX defined to be %d.\n",ARG_MAX);
#else
printf("no symbol for ARG_MAX.\n");
#endif
long int arg_max=0;
//get the value system defined.
arg_max = sysconf(_SC_ARG_MAX);
//if system doesn't provide a default value
if(arg_max < 0)
{
//if system doesn't support this attribute.
if(errno != 0)
{
if(errno == EINVAL)
printf("name not valid.\n");
else
printf("sysconf error.\n");
}
//support this attribute and we can do something by ourself.
else
{
printf("no limit.\n");
}
}
//system has provided a default value
else
{
printf("_SC_ARG_MAX %ld.\n",arg_max);
}
#ifdef _POSIX_ADVISORY_INFO
printf("ADVISORY_INFO defined to be %d.\n",_POSIX_ADVISORY_INFO);
#else
printf("no symbol for ADVISORY_INFO.\n");
#endif
long int advisory_info=0;
advisory_info=sysconf(_SC_ADVISORY_INFO);
if (advisory_info<0) {
if (errno!=0) {
if (errno==EINVAL) {
printf("name not valid.\n");
}else{
printf("sysconf error.\n");
}
}else {
printf("no limit");
}
}else {
printf("_SC_ADVISORY_INFO defined to be %d.\n",_SC_ADVISORY_INFO);
}
return 0;
}
输出结果:
ARG_MAX defined to be 262144.
_SC_ARG_MAX 262144.
ADVISORY_INFO defined to be -1.
no limit
后两行表明虽然系统定义了 ,但是并未给我们提供默认值 所以需要我们自己去根据实际情况实现。
实际应用--为路径名开辟空间
很多时候需要用户输入文件路径名,我们往往用一个字符数组来保存这个路径名,所以获取系统所支持最大路径名可以提高代码移植.
#include<errno.h>
#include<limits.h>
#include<unistd.h>
//先判断是否在编译时提供了PATH_MAX值
#ifdef PATH_MAX
static int pathmax=PATH_MAX;
#else
static int pathmax=0;
#endif
#define PATH_MAX_GUESS 256
//size!=null则用于保存开辟空间大小
char * path_alloc(int *size){
char *ptr;
if(pathmax==0){
errno=0;
if( (pathmax=pathconf("/",_PC_PATH_MAX)) <0){
//pathconf返回了负数,但是并没有出错,只是说明该值不确定性
if(errno==0){
pathmax=PATH_MAX_GUESS;
}
else{
perror("Error in pathconf .");
}
}
else{
//解决 根目录 “/” 开辟的空间
pathmax++;
}
}
//因为limits中没有为字符串的null预留空间
if( (ptr=malloc(pathmax+1)) ==NULL){
perror("Error in malloc .");
}
if(size!=NULL){
*size=pathmax+1;
}
return ptr;
}
所以可以看出三种函数为我们处理多平台兼容性提供了很大的便利性。