目录
1 getopt()
2 getopt_long()
3 dlopen()
4 分区信息和文件属性
4.1 fstatfs/statfs
4.2 statvfs/fstatvfs
4.3 stat/fstat
1 getopt()
getopt被用来解析命令行选项参数,就不用自己处理argv了。
头文件:#include <unistd.h>
原型:int getopt(int argc, char * const argv[], const char *optstring);
参数:optstring - 选项字符串
- 单个字符,表示选项;
- 单个字符后接一个冒号:表示该选项后必须跟一个参数。参数紧跟在选项后或者以空格隔开。该参数的指针赋给optarg;
- 单个字符后跟两个冒号,表示该选项后必须跟一个参数。参数必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。
例1:optstring为"a:b:cd::e"。对应到命令行就是-a ,-b ,-c ,-d, -e ;其中a b d后面有冒号,则后面必须跟一个参数;而c e后面没有冒号,所有不用跟参数。比如-a 11或-a11,11表示a的参数。
头文件与之相关变量(不用自己定义,直接使用):
-
extern char *optarg; //选项的参数指针
-
extern int optind, //下一个检索位置:下一次调用getopt的时,从optind存储的位置处重新开始检查选项。
-
extern int opterr, //是否将错误信息输出到stderr:当opterr=0时,getopt不向stderr输出错误信息。
-
extern int optopt; //不在选项字符串optstring中的选项:当命令行选项字符不包括在optstring中或者选项缺少必要的参数时,该选项存储在optopt中,getop()返回'?’、
例1:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int ch;
while( (ch = getopt(argc, argv, "ab:c::")) != -1 )
{
switch(ch)
{
case 'a':
printf("option = a, optopt = %c, optarg = %s\n", optopt, optarg);
break;
case 'b':
printf("option = b, optopt = %c, optarg = %s\n", optopt, optarg);
break;
case 'c':
printf("option = c, optopt = %c, optarg = %s\n", optopt, optarg);
break;
case '?':
printf("option =? , optopt = %c, optarg = %s\n", optopt, optarg);
break;
default:
printf("default, ch = %c\n",ch);
break;
}
}
return 0;
}
例2:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int ch;
printf("optind:%d,opterr:%d\n",optind,opterr);
while( (ch = getopt(argc, argv, "ab:c::")) != -1 )
{
printf("optind: %d\n", optind);
switch(ch)
{
case 'a':
printf("option = a, optopt = %c, optarg = %s\n", optopt, optarg);
break;
case 'b':
printf("option = b, optopt = %c, optarg = %s\n", optopt, optarg);
break;
case 'c':
printf("option = c, optopt = %c, optarg = %s\n", optopt, optarg);
break;
case '?':
printf("option =? , optopt = %c, optarg = %s\n", optopt, optarg);
break;
default:
printf("default, ch = %c\n",ch);
break;
}
}
return 0;
}
又上面可以看出:optind和opterr的初始值都为1,opterr非零表示产生的错误要输出到stderr上。optind的初值为1是因为,main函数的那两个参数了,argc表示参数的个数,argv[]表示每个参数字符串,./test -a -b hello -cwlord,实际上真正的参数是用第二个-a 开始,也就是argv[1],所以optind的初始值为1;
2 getopt_long()
头文件:#include<getopt.h>
函数原型:int getopt_long(int argc, char * const argv[],const char *optstring, const struct option *longopts,int *longindex)
参数:optstring - 选项字符串
longopts - 是一个结构的实例
struct option
{
const char *name; /*name表示的是长参数名*/
int has_arg; /*has_arg有3个值:
1、no_argument(或者是0),表示该参数后面不跟参数值;
2、required_argument(或者是1),表示该参数后面一定要跟个参数值
3、optional_argument(或者是2),表示该参数后面可以跟,也可以不跟参数值
*/
int *flag; /*用来决定,getopt_long()的返回值到底是什么。如果flag是null,则函数会返回与
该项option匹配的val值*/
int val; /*和flag联合决定返回值*/
}
longindex - 如果longindex非空,它指向的变量将记录当前找到参数符合longopts里的第几个元素的描述,即是longopts的下标值
#include <stdio.h>
#include <unistd.h>
#include<getopt.h>
static struct option long_options[] =
{
{"add", no_argument, NULL, 'a'},
{"back", required_argument, NULL, 'b'},
{"create", required_argument, NULL, 'c'},
{0, 0, 0, 0},
};
int main(int argc, char **argv)
{
int ch;
int option_index = 0;
printf("optind:%d,opterr:%d\n",optind,opterr);
while( (ch = getopt_long(argc, argv, "ab:c::",long_options, &option_index)) != -1 )
{
printf("optind: %d\n", optind);
switch(ch)
{
case 'a':
printf("option = a, optopt = %c, optarg = %s\n", optopt, optarg);
break;
case 'b':
printf("option = b, optopt = %c, optarg = %s\n", optopt, optarg);
break;
case 'c':
printf("option = c, optopt = %c, optarg = %s\n", optopt, optarg);
break;
case '?':
printf("option =? , optopt = %c, optarg = %s\n", optopt, optarg);
break;
default:
printf("default, ch = %c\n",ch);
break;
}
printf ("option %s\n", long_options[option_index].name);
}
return 0;
}
3 dlopen()
dlopen() 功能是以指定模式打开指定的动态链接库文件,并返回一个句柄给dlsym()的调用进程。使用dlclose()来卸载打开的库。
dlopen这个函数加载由以null结尾的字符串文件名命名的动态共享对象(共享库)文件,并为加载的对象返回不透明的“句柄”。此句柄与 dlopen API 中的其他函数一起使用,例如dlsym(),dladdr(),dlinfo()和dlclose()
#include <dlfcn.h>
void *dlopen(const char *filename, int flags);
void *dlsym(void *handle, const char *symbol);
int dlclose(void *handle);
char *dlerror(void);
参数:
- filename:库路径;
- flags:标志指明是否立刻计算库的依赖性
- RTLD_LAZY:立刻计算库的依赖性;
- RTLD_NOW:在需要的时候才计算库的依赖性;
- handle:由dlopen打开动态链接库后返回的指针;
- symbol:是要求获取的函数的名称,函数返回值是void*,指向函数的地址,供调用使用
注意:编译时候要加入 -ldl (指定dl库) -rdynamic(通知链接器将所有符号添加到动态符号表中(目的是能够通过使用 dlopen 来实现向后跟踪)
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#define LIB_PATH "./libsd.so"
typedef int (*Callback_func)(int, int);
int main()
{
void *dlhandler;
char *error;
Callback_func func = NULL;
dlhandler = dlopen(LIB_PATH, RTLD_LAZY);
if(dlhandler == NULL)
{
fprintf(stderr,"%s\n",dlerror());
exit(-1);
}
dlerror();
func = dlsym(dlhandler,"sumab");
printf("%d\n",func(1,2));
dlclose(dlhandler);
return 0;
}
4 分区信息和文件属性
4.1 fstatfs/statfs
#include <sys/vfs.h> /* or <sys/statfs.h> */
int statfs(const char *path, struct statfs *buf);
int fstatfs(int fd, struct statfs *buf);
参数:
- path: 位于需要查询信息的文件系统的文件路径名。
- fd: 位于需要查询信息的文件系统的文件描述词。
- buf:以下结构体的指针变量,用于储存文件系统相关的信息
struct statfs {
long f_type; /* 文件系统类型 */
long f_bsize; /* 经过优化的传输块大小,剩余空间大小k */
long f_blocks; /* 文件系统数据块总数 */
long f_bfree; /* 可用块数 */
long f_bavail; /* 非超级用户可获取的块数 */
long f_files; /* 文件结点总数 */
long f_ffree; /* 可用文件结点数 */
fsid_t f_fsid; /* 文件系统标识 */
long f_namelen; /* 文件名的最大长度 */
};
返回说明:
#include <stdio.h>
#include <sys/vfs.h>
int main()
{
long totalBlocks = 0;
long freeDisk = 0;
const char *path = "/root/work/demo";
struct statfs diskinfo;
int ret = statfs(path, &diskinfo);
if(ret != 0)
{
printf("statfs error");
}
totalBlocks = diskinfo.f_bsize;
freeDisk = diskinfo.f_bfree * totalBlocks; //剩余空间大小
printf("totalBlocks = %ld, freeDisk = %ld\n",totalBlocks, freeDisk);
return 0;
}
4.2 statvfs/fstatvfs
#include <sys/statvfs.h>
int statvfs(const char *path, struct statvfs *buf);
int fstatvfs(int fd, struct statvfs *buf);
参数:
- path: 位于需要查询信息的文件系统的文件路径名。
- fd: 位于需要查询信息的文件系统的文件描述词。
- buf:以下结构体的指针变量,用于储存文件系统相关的信息
struct statvfs {
unsigned long f_bsize; /*文件系统块大小*/
unsigned long f_frsize; /*碎片大小*/
fsblkcnt_t f_blocks; /*fs的大小(以f_frsize为单位)*/
fsblkcnt_t f_bfree; /*可用块数*/
fsblkcnt_t f_bavail; /*非根的可用块数*/
fsfilcnt_t f_files; /*#索引节点*/
fsfilcnt_t f_ffree; /*#空闲索引节点*/
fsfilcnt_t f_favail; /*非根目录的空闲索引节点数*/
unsigned long f_fsid; /*文件系统ID*/
unsigned long f_flag; /*装载标志*/
unsigned long f_namemax; /*最大文件名长度*/
};
- 总容量 = f_bsize * f_blocks;
- 剩余空间 = f_bfree * f_frsize;
- 可用空间 = f_bavail * f_bsize
#include <stdio.h>
#include <sys/statvfs.h>
int main()
{
long totalBlocks = 0;
long freeDisk = 0;
struct statvfs diskinfo;
int ret = statvfs("./", &diskinfo);
if(ret != 0)
{
printf("statfs error");
}
long AllTotalSize = diskinfo.f_bsize*diskinfo.f_blocks; /*总容量*/
long freeSize = diskinfo.f_bfree * diskinfo.f_frsize; /*剩余空间大小*/
long usrFreeSize = diskinfo.f_bavail * diskinfo.f_bsize; /*可用剩余空间大小*/
printf("AllTotalSize = %ld\n", AllTotalSize);
printf("freeSize = %ld\n", freeSize);
printf("usrFreeSize = %ld\n", usrFreeSize);
return 0;
}
4.3 stat/fstat
#include <unistd.h>
#include <sys/stat.h>
int stat(const char *file_name, struct stat *buf);
int fstat(int fd, struct stat *buf);
函数说明:将参数file_name所指的文件状态,复制到参数buf所指的结构中;
struct stat
{
dev_t st_dev; /* ID of device containing file -文件所在设备的ID*/
ino_t st_ino; /* inode number -inode节点号*/
mode_t st_mode; /* protection -保护模式?*/
nlink_t st_nlink; /* number of hard links -链向此文件的连接数(硬连接)*/
uid_t st_uid; /* user ID of owner -user id*/
gid_t st_gid; /* group ID of owner - group id*/
dev_t st_rdev; /* device ID (if special file) -设备号,针对设备文件*/
off_t st_size; /* total size, in bytes -文件大小,字节为单位*/
blksize_t st_blksize; /* blocksize for filesystem I/O -系统块的大小*/
blkcnt_t st_blocks; /* number of blocks allocated -文件所占块数*/
time_t st_atime; /* time of last access -最近存取时间*/
time_t st_mtime; /* time of last modification -最近修改时间*/
time_t st_ctime; /* time of last status change - */
};
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
int main()
{
struct stat buf;
int result;
result = stat ("./demo", &buf);
if (result != 0)
{
perror ("Failed to stat");
}
else
{
/* 文件的大小,字节为单位 */
printf("file size : %ld\n", buf.st_size);
/* 文件创建的时间 */
printf("time of creation of the file : %s\n",ctime (&buf.st_ctime));
/* 最近一次修改的时间 */
printf("time of last modification of the file: %s\n",ctime (&buf.st_mtime));
/* 最近一次访问的时间 */
printf("time of last access of the file : %s\n",ctime (&buf.st_atime));
}
return 0;
}
5 文件/目录相关
5.1 access
#include <unistd.h>
int access(const char *pathname, int mode);
参数:
- pathname:文件路径
-
mode:访问判断模式
- R_OK 只判断是否有读权限
- W_OK 只判断是否有写权限
- X_OK 判断是否有执行权限
- F_OK 只判断是否存在
返回值:0 - 成功
#include <stdio.h>
#include <unistd.h>
int main()
{
const char *path = "./test";
int ret = access(path, X_OK | W_OK);
if(ret != 0)
{
printf("ret[ %d ]\n",ret);
}
else
{
printf("access succes!\n");
}
return 0;
}
5.2 chdir()/opendir()/readdir()
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
struct dirent
{
long d_ino; /* inode number 索引节点号 */
off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
unsigned short d_reclen; /* length of this d_name 文件名长 */
unsigned char d_type; /* the type of d_name 文件类型 */
char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}
#include <stdio.h>
#include <dirent.h>
#include <strings.h>
int main()
{
DIR *dirp = opendir(".");
struct dirent *file;
while (file = readdir(dirp)) //遍历目录下的文件
{
/** 过滤掉文件 */
if ((0 == strncasecmp(file->d_name, ".", 1)))
{
continue;
}
printf("filename: %s\n", file->d_name); //文件名
}
closedir(dirp);
return 0;
}
#include <unistd.h>
int chdir(const char *path);
功能:用户将当前的工作目录改变成以参数路径所指的目录
返回值:0 - 成功
#include <stdio.h>
#include <unistd.h>
int main()
{
int ret = chdir("/root/work");
if(ret != 0)
{
printf("ret[ %d ]\n", ret); //文件名
}
return 0;
}