6.1 引言

UNIX系统的正常运行需要使用大量与系统有关的数据文件,这些文件都是ASCII文本文件,并且使用标准I/O库读这些文件。

6.2 口令文件

UNIX口令文件是/etc/passwd,每一行包含下图中的各字段,字段之间用冒号分隔,这些字段包含在<pwd.h>中定义的passwd结构中。

两个获取口令文件项的函数:

#include <pwd.h>struct passwd *getpwuid(uid_t uid);
struct passwd *getpwnam(const char *name);// 两个函数返回值:若成功,返回指针;若出错,返回NULL
  • 这两个函数都返回一个指向passwd结构的指针,该结构已由这两个函数在执行时填入信息;
  • passwd结构通常是函数内部的静态变量,只要调用任一相关函数,其内容就会被重写。
/* The passwd structure.  */
struct passwd
{char *pw_name;     /* Username.  */char *pw_passwd;        /* Password.  */__uid_t pw_uid;     /* User ID.  */__gid_t pw_gid;      /* Group ID.  */char *pw_gecos;     /* Real name.  */char *pw_dir;          /* Home directory.  */char *pw_shell;       /* Shell program.  */
};

下列3个函数用于查看整个口令文件:

#include <pwd.h>struct passwd *getpwent(void);// 返回值:若成功,返回指针;若出错或到达文件尾端,返回NULL
void setpwent(void);
void endpwent(void);
  • getpwent函数返回口令文件中的下一个记录项;
  • setpwent函数用来将getpwent函数的读写地址指向密码文件开头;
  • endpwent函数关闭这些文件,在使用getpwent函数查看完口令文件后,一定要调用endpwent关闭这些文件。

6.3 阴影口令

  • 加密口令是经单向加密算法处理过的用户口令副本,不能从加密口令猜测到原来的口令;
  • 系统将加密口令存放在阴影口令文件(/etc/shadow)中,该文件的主要内容包括如下内容,其中用户登录名加密口令是必需的:

下面一组函数用于访问阴影口令文件:

#include <shadow.h>struct spwd *getspnam(const char* name);
struct spwd *getspent(void);// 两个函数返回值:若成功,返回指针;若出错,返回NULL
void setspent(void);
void endspent(void);

6.4 组文件

UNIX组文件(/etc/group)包含下图所示字段,这些字段包含在<grp.h>中所定义的group结构中:

  • 字段gr_mem是一个指针数组,其中每个指针指向一个属于该组的用户名,该数组以null指针结尾。

可以用下列两个函数来查看组名或数值组ID:

#include <grp.h>struct group *getgrgid(gid_t gid);
struct group *getgrnam(const char *name);// 两个函数返回值:若成功,返回指针;若出错,返回NULL
  • 这两个函数返回一个指向静态变量的指针,在每次调用时都重写该静态变量。

下列3个函数用于搜索整个组文件:

#include <grp.h>struct group *getgrent(void);// 返回值:若成功,返回指针;若出错或到达文件尾端,返回NULL
void setgrent(void);
void endgrent(void);
  • setgrent函数打开组文件(如若它尚未打开)并反绕它;
  • getgrent函数从组文件中读下一个记录,如若该文件尚未打开,则先打开它;
  • endgrent函数关闭组文件。

6.5 附属组ID

下面3个函数用于获取和设置附属组ID:

#include <unistd.h>
int getgroups(int gidsetsize, gid_t grouplist[]);// 返回值:若成功,返回附属组ID数量;若出错,返回-1#include <grp.h>    /* on Linux */
#include <unistd.h>   /* on FreeBSD, Mac OS X, and Solaris */
int setgroups(int ngroups, const gid_t grouplist[]);#include <grp.h>  /* on Linux and Solaris */
#include <unistd.h>   /* on FreeBSD and Mac OS X */
int initgroups(const char *username, gid_t basegid);// 两个函数的返回值:若成功,返回0;若出错,返回-1
  • getgroups将进程所属用户的各附属组ID填写到数值grouplist中,填写入该数组的附属组ID数最多为gidsetsize个;实际填写到数组中的附属组ID数由函数返回,若gidsetsize0,则函数只返回附属组ID数,而对数组grouplist则不做修改;
  • setgroups由超级用户调用来为调用进程设置附属组ID表,grouplist是组ID数组,而ngroups说明数组中的元素数,ngroups的值不能大于NGROUPS_MAX
  • initgroups函数调用setgroups,它先读整个组文件,对username确定其组的成员关系;然后,它调用setgroups,为该用户初始化附属组ID表;除了在组文件中找到username的所有组,initgroups也在附属组ID表中包含了basegidbasegidusername在口令文件中的组ID。

6.6 实现区别

6.7 其他数据文件


一般情况下,对于每个数据文件至少有3个函数:

  • get函数:读下一个记录,如果需要,还会打开该文件。此种函数通常返回指向一个结构的指针。当已达到文件尾端时返回空指针。大多数get函数返回指向一个静态存储类结构的指针,如果要保存其内容,则需复制它;
  • set函数:打开相应数据文件(如果尚未打开),然后反绕该文件。如果希望在相应文件起始处开始处理,则调用此函数;
  • end函数:关闭相应数据文件。在结束了对相应数据文件的读、写操作后,总应调用此函数以关闭所有相应文件。

6.8 登录账户记录

6.9 系统标识

uname函数返回与主机和操作系统有关的信息:

#include <sys/utsname.h>int uname(struct utsname *name);// 返回值:若成功,返回非负值;若出错,返回-1
  • 该函数的参数是一个utsname结构的地址,其内容由函数填写。

gethostname函数只返回主机名,该名字通常就是TCP/IP网络上主机的名字:

#include <unistd.h>int gethostname(char *name, int namelen);// 返回值:若成功,返回0;若出错,返回-1
  • namelen参数指定name缓冲区长度,如若提供足够的空间,则通过name返回的字符串以null字节结尾;如若没有提供足够的空间,则没有说明通过name返回的字符串是否以null结尾;
  • 最大主机名长度是HOST_NAME_MAX

6.10 时间和日期例程

UNIX内核提供的基本时间服务是计算自协调世界时(Coordinated Universal Time,UTC)公元1970年1月1日00:00:00这一特定时间以来经过的秒数,这种秒数是以数据类型time_t表示的,称为日历时间,日历时间包括时间日期

time函数返回当前时间和日期:

#include <time.h>time_t time(time_t *calptr);// 返回值:若成功,返回时间值;若出错,返回-1
  • 时间值作为函数返回;
  • 如果参数非空,则时间值也存放在由calptr指向的单元内。

POSIX.1的实时扩展增加了对多个系统时钟的支持,时钟通过clockid_t类型进行标识,下图给出了标准值:

clock_gettime函数用于获取指定时钟的时间,返回的时间在timespec结构中,它把时间表示为纳秒

struct timespec {__kernel_time_t tv_sec;         /* seconds */long       tv_nsec;        /* nanoseconds */
};
#include <sys/time.h>int clock_gettime(clockid_t clock_id, struct timespec *tsp);// 返回值:若成功,返回0;若出错,返回-1

clock_getres函数把参数tsp指向的timespec结构初始化为与clock_id参数对应的时钟精度:

#include <sys/time.h>int clock_getres(clockid_t clock_id, struct timespec *tsp);// 返回值:若成功,返回0;若出错,返回-1

clock_settime函数用于对特定的时钟设置时间:

#include <sys/time.h>int clock_settime(clockid_t clock_id, const struct timespec *tsp);// 返回值:若成功,返回0;若出错,返回-1

gettimeofday函数获取当前时间:

#include <sys/time.h>int gettimeofday(struct timeval *restrict tp, void *restrict tzp);// 返回值:总是返回0
  • gettimeofday函数以距特定时间(1970年1月1日00:00:00)的秒数的方式将当前时间存放在tp指向的timeval结构中,而该结构将当前时间表示为微秒
/* A time value that is accurate to the nearestmicrosecond but also has a range of years.  */
struct timeval
{__time_t tv_sec;       /* Seconds.  */__suseconds_t tv_usec;   /* Microseconds.  */
};

一旦取得这种从上述特定时间经过的秒数的整型时间值后,通常需要调用函数将其转换成分解的时间结构,然后调用另一个函数生成人们可读的时间和日期,各种时间函数之间的关系如下:

localtimegmtime将日历时间转换成分解的时间,并将这些存放在一个tm结构中:

/* ISO C `broken-down time' structure.  */
struct tm
{int tm_sec;            /* Seconds. [0-60] (1 leap second) */int tm_min;            /* Minutes. [0-59] */int tm_hour;           /* Hours.   [0-23] */int tm_mday;           /* Day.     [1-31] */int tm_mon;            /* Month.   [0-11] */int tm_year;           /* Year - 1900.  */int tm_wday;         /* Day of week. [0-6] */int tm_yday;            /* Days in year.[0-365] */int tm_isdst;         /* DST.     [-1/0/1]*/# ifdef   __USE_MISClong int tm_gmtoff;       /* Seconds east of UTC.  */const char *tm_zone;     /* Timezone abbreviation.  */
# elselong int __tm_gmtoff;     /* Seconds east of UTC.  */const char *__tm_zone;   /* Timezone abbreviation.  */
# endif
};
#include <time.h>struct tm *gmtime(const time_t *calptr);
struct tm *localtime(const time_t *calptr);// 两个函数的返回值:指向分解的tm结构的指针;若出错,返回NULL
  • localtime将日历时间转换成本地时间(考虑到本地时区和夏时令标志);
  • gmtime将日历时间转换成协调统一时间的年、月、日、时、分、秒、周日分解结构。

mktime以本地时间的年、月、日等作为参数,将其变换成time_t值:

#include <time.h>time_t mktime(struct tm *tmptr);// 返回值:若成功,返回日历时间;若出错,返回-1

strftime函数通过可用的多个参数来定制产生的字符串:

#include <time.h>size_t strftime(char *restrict buf, size_t maxsize,const char *restrict format,const struct tm *restrict tmptr);
size_t strftime_l(char *restrict buf, size_t maxsize,const char *restrict format,const struct tm *restrict tmptr, locale_t locale);// 两个函数的返回值:若有空间,返回存入数组的字符数;否则返回0
  • strftime_l允许调用者将区域指定为参数,除此之外,strftimestrftime_l函数是相同的,strftime使用通过TZ环境变量指定的区域;
  • tmptr参数是要格式化的时间值,由一个指向分解时间值tm结构的指针说明;
  • 格式化结果存放在一个长度为maxsize个字符的buf数组中,如果buf长度足以存放格式化结果及一个null终止符,则该函数返回在buf中存放的字符数(不包括null终止符),否则该函数返回0
  • format参数控制时间值的格式,其转换说明如下:

    strptime函数是strftime的反过来版本,把字符串时间转换成分解时间:
#include <time.h>char *strptime(const char *restrict buf, const char *restrict format, struct tm *restrict tmptr);// 返回值:指向上次解析的字符的下一个字符的指针;否则,返回NULL
  • format参数给出了buf参数指向的缓冲区内字符串的格式,其转换说明如下:

6.11 实例代码

chapter6

UNIX环境高级编程——系统数据文件和信息相关推荐

  1. Unix环境高级编程-系统数据文件和信息

    unix口令文件/etc/passwd 包含了下表所示的字段: 系统定义了两个获取口令文件项的函数,在给出用户登录名或数值用户ID后,这两个函数能够查看相关项. struct passwd *getp ...

  2. (三) 一起学 Unix 环境高级编程 (APUE) 之 文件和目录

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  3. UNIX环境高级编程笔记之文件I/O

    一.总结 在写之前,先唠几句,<UNIX环境高级编程>,简称APUE,这本书简直是本神书,像我这种小白,基本上每看完一章都是"哇"这种很吃惊的表情.其实大概三年前,那会 ...

  4. 开发日记-20190827 关键词 读书笔记《Unix环境高级编程(第二版)》DAY 3

    Referred Blogs 文件描述符标志,文件状态标志 Linux中文件描述符fd和文件指针flip的理解 Linux编程–文件描述符fd 文件共享 Unix支持在不同进程间共享文件. 内核使用了 ...

  5. 《unix环境高级编程》笔记4——系统数据文件和信息

    文章目录 系统数据文件和信息 口令文件 获取口令文件 getwpuid getpwnam 阴影口令 组文件 附属组ID 查看附属组ID 其他文件 登录账户记录: 系统标识 uname gethostn ...

  6. 文件和目录(二)--unix环境高级编程读书笔记

    在linux中,文件的相关信息都记录在stat这个结构体中,文件长度是记录在stat的st_size成员中.对于普通文件,其长度可以为0,目录的长度一般为1024的倍数,这与linux文件系统中blo ...

  7. unix环境高级编程(上)-文件篇

    目录 前言 unix基础知识 unix标准化和实现 unix提供的文件IO 文件和目录 标准IO 系统数据文件 前言 笔者将<unix环境高级编程>主要内容总结为三篇:文件篇,进程篇,高级 ...

  8. 5w字总结 Unix系统编程学习笔记(面试向)(Unix环境高级编程/Unix环境程序设计)

    文章目录 一.计算 C语言的数据表示与处理 计算 C语言的基本运算操作 内存表和符号表 类型转换 函数类型的分析 指令 复合指令 句法 函数 函数激活(Activation Record) 函数激活定 ...

  9. unix环境高级编程 pdf_UNIX系统编程宝典,每一本都值得程序员珍藏

    这几本UNIX系统编程宝典,重印无数次,几代程序员都视如珍宝的几本书,小编在出版圈里快十年了,见证了这本书图灵版.异步社区版的出版.营销,对这套书倾注了一定的感情.今天继续分享给你们,好书总会有人还不 ...

最新文章

  1. 从入门到高阶,读懂机器学习需要哪些数学知识
  2. 《Excel最强功能-数据透视表》 网课笔记
  3. Java TCP/IP Socket 编程 笔记
  4. 互联网日报 | 京东开启最大规模校招;特斯拉西部首个交付中心在蓉投入使用;嫦娥五号上升器点火起飞...
  5. vb 6 MDI窗体图片自适应源码
  6. MFC基础教程之窗口定义(一)
  7. 利用yarn多队列实现hadoop资源隔离
  8. Flutter Android权限问题
  9. 如何制定软件开发计划
  10. 彻底讲清楚ZooKeeper分布式锁的实现原理【石杉的架构笔记】
  11. 通信协议之IIC总线
  12. 下载2019年7月实行的新标准JTT808-2019道路运输车辆卫星定位系统终端通讯协议及数据格式
  13. 什么是敏感信息检测,敏感信息检测,安全视图 | 云效
  14. 为什么苹果手机通话的时候不能录音?
  15. 以后有了孩子要起名就在这上面选啊!
  16. 喧喧 2.5 发布,新增客户端自动升级,优化界面交互性能
  17. dw在html中删除css样式表,DW里CSS的详细介绍
  18. SCons教程(7) 文件操作
  19. 视频教程免费分享:嵌入式stm32项目开发之心率检测仪的设计与实现
  20. Navicat Data Modeler(ndm2)数据模型逆向生成表

热门文章

  1. 安防监控如何秒变超速终结者?
  2. Rime输入法引擎配置( 小狼毫输入法常用设置)
  3. 什么是品牌营销?学会正确推广您的业务
  4. python3.7安装pycrypto
  5. 東京喰種_经典台词中日双语1
  6. 【设计模式】第4章·工厂方法模式
  7. arm服务器芯片主板,技嘉展示Ampere Altra ARM服务器的R272-P30主板
  8. 关于51单片机串口中断的理解
  9. 搜索引擎究竟是如何区分原创和伪原创的呢?
  10. FX粒子(Niagara系统)、顶点法线材质函数、材质参数集——雪和简单地形材质积雪效果