Unix高级环境编程(APUE)-----系统数据文件和信息

版权声明: https://blog.csdn.net/zl6481033/article/details/91378657

1、引言

        有时候一些操作需要使用一些与系统有关的数据文件,例如口令文件/etc/passwd和组文件/etc/group就是经常由多中程序使用的两个文件,用户每次登入UNIX系统,以及每次执行ls -l命令时都要使用口令文件。这些文件都是ASCII文本文件,并且使用标准IO库读这些文件,但是这样很麻烦,系统其实也提供了一些函数来处理。

2、口令文件

        UNIX口令文件包含下表中的字段,这些字段包含在<pwd.h>定义的passwd结构中。

        

        定义了两个存取口令中信息的函数,再给出用户登录名或数值用户ID后,这两个函数就能查看相关记录:

#include <sys/types.h>
#include <pwd.h>

struct passwd *getpwnam(const char *name);

struct passwd *getpwuid(uid_t uid);

        getwuid由ls程序使用,以便将包含在一个i节点中数值用户ID映照为用户登录名,getpwnam在键入登录名时由login程序使用,这两个函数都返回一个指向passwd结构的指针,该结构已由这两个函数在执行时填入了所需的信息,该结构通常是在相关函数内的静态变量,只要调用相关函数,其内容就会被重写。如果只是查看一个登录名或用户ID,那么上面两个函数就能满足要求,但是也有些程序要查看整个口令文件,下面三个函数可用于此。

#include <sys/types.h>
#include <pwd.h>

struct passwd *getpwent(void);

void setpwent(void);

void endpwent(void);

        调用getpwent时,返回口令文件中的下一个记录,返回一个填好的passwd结构的指针,每次调用这个函数都会重写这个结构,在第一次掉用该函数时,它打开使用的各个文件,在使用本函数时,对口令文件中各个记录安排顺序并无要求。setpwent反绕它所使用的文件,endpwent关闭这些文件。

3、阴影口令

        其实阴影口令文件就是将上一节的口令加密之后存放的文件,这个文件至少包括用户名和加密口令。阴影口令一般不应该是一般用户可以读取的。

4、组文件

        UNIX组文件包含下表中的字符段,这些字段包含在<grp.h>中所定义的group结构中。

        

        字段gr_mem是一个指针数组,其中指针各指向一个属于该组的用户名,该数组以null结尾。可以用下面两个函数来查看组名或数值组ID。

#include <sys/types.h>
#include <grp.h>

struct group *getgrnam(const char *name);

struct group *getgrgid(gid_t gid);

        和对口令文件的操作一样,这两个函数通常也返回一个指向静态变量的指针,在每次调用时都重写该静态变量。如果要搜索整个组文件,则必须使用另外几个函数,下列三个函数类似与口令文件中的三个函数。

#include <sys/types.h>
#include <grp.h>

struct group *getgrent(void);

void setgrent(void);

void endgrent(void);

        setgrent打开组文件并反绕它,getgrent从组文件中读下一个记录,如果该文件还没有打开,那就先打开。endgrent关闭组文件。

5、添加组ID

        为了存取和设置添加组ID提供了下列三个函数:

#include <sys/types.h>
#include <unistd.h>
#include <grp.h>

int getgroups(int size, gid_t list[]);

int setgroups(size_t size, const gid_t *list);

int initgroups(const char *user, gid_t group);

        getgroups将进程所属用户的各添加组ID填写到数组list中,填写入该数组的添加组ID最多是size个,实际填写到数组中的添加组ID数由函数返回。如果size为0,则函数只返回添加组ID数,而对数组list不做修改。

        setgroups可由超级用户调用以便为调用进程设置添加组ID表。list是组ID数组,size说明了数组中的元素数。

        通常只有initgroups函数调用setgroups,initgroups读整个组文件,然后用username确定其组成员的关系,然后调用setgroup以便为该用户初始化添加组ID表,因为initgroups调用setgroups,所以只有超级用户才能调用initgroups。initgroups只有少数的几个程序调用,例如login程序在用户登录时调用该函数。

6、其他数据文件

        除了口令文件和组文件两个系统数据文件还有很多其他文件,一般而言每个数据文件至少有三个函数:

        (1)get函数:读下一个记录,如果还需要打开该文件,此种函数通常返回指向一个结构的指针,当以达到文件尾端时返回空指针,大多数get函数返回一个指向一个静态存储类结构的指针,如果要保存其内容,则需要复制它。

        (2)set函数:打开相应的数据文件(如果尚未打开),然后反绕该文件,如果希望在相应文件起始处就开始处理,则调用此函数。

        (3)end函数:关闭相应的数据文件,在结束了对相应数据文件的读、写操作之后,总是应该调用此函数关闭所有相关文件。

7、登录会计

        大多数UNIX系统会提供下列两个数据文件:utmp文件,记录当前登录进系统的各个用户;wtmp文件,跟踪各个登录文件和注销文件。

        

        登录时,login程序填写这样一个结构,然后将其写入到utmp文件中,也写到到wtmp文件中,注销时,init进程将utmp文件中相应的记录擦除,并添加一个新纪录到wtmp文件中,读wtmp文件中的该注销记录,其ut_name字段清除为0,在系统再启动时,以及更改系统时间和日期齐纳后都会在wtmp文件中填写特殊的记录项,who程序读取ump文件,并以可读格式打印其内容,last命令,读取wtmp文件并打印所选择的记录。

8、系统标识

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

#include <sys/utsname.h>

int uname(struct utsname *buf);

        通过该函数的参数向其传递一个utsname结构的地址,然后函数填写这个结构,下图为这个结构的一些字段。

       

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

#include <unistd.h>

int gethostname(char *name, size_t len);

        通过name返回的字符串以null结尾,<sys/param.h>中的常数MAXHOSTNAMELEN规定了此名字的最大长度,如果宿主主机连接到TCP/IP网络中,此主机名通常是该主机的完整域名。hostname命令可以用来存取和设置主机名。

9、时间与日期例程

        UNIX内核提供的基本是减服务是国际标准时间公元19701月1日00:00:00来经过的秒数,这种秒数是以数据类型time_t表示的,称之为日历时间。日历时间包括时间和日期。UNIX在这方面与其他操作系统的区别是:(1)以国际标准时间而非本地时间计时。(2)可以自动进行转换,例如变换到夏日至。(3)将时间和日期作为量值被保存。time函数返回当前时间和日期。

#include <time.h>

time_t time(time_t *tloc);

时间值作为函数值返回,如果参数非null,则时间值也存放在由tloc指向的单元内。

        localtime函数的作用是time_t大整数转换为程序员喜欢的tm结构,并且是将日历时间转换为本地时间。

#include <time.h>

struct tm *localtime(const time_t *timep);

        struct time_t的成员如下:

struct tm {
    int tm_sec;         /* 秒,支持润秒 [0 - 60] */
    int tm_min;         /* 分钟 [0 - 59] */
    int tm_hour;        /* 小时 [0 - 23] */
    int tm_mday;        /* 一个月中的第几天 [1 - 31] */
    int tm_mon;         /* 月份 [0 - 11] */
    int tm_year;        /* 年,从 1900 开始 */
    int tm_wday;        /* 一星期中的第几天 [0 - 6] */
    int tm_yday;        /* 一年中的第几天 [0 - 365] */
    int tm_isdst;       /* 夏令时调整,基本不用,如果怕有影响可以设置为 0 */
};

函数gmtime和localtime函数相同,作用是将time_t大整数转化为tm结构体。

#include <time.h>
 
struct tm *gmtime(const time_t *timep);

10、小结

        所有UNIX系统上都使用口令文件和组文件,前面也介绍了关于这些文件的函数以功能。

猜你喜欢

转载自blog.csdn.net/zl6481033/article/details/91378657