APUE读书笔记-第六章 系统数据文件和信息

2024-08-22 04:38

本文主要是介绍APUE读书笔记-第六章 系统数据文件和信息,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

昨天看完了,今天来看看第六章。感觉第六章的内容不是非常重要。简单看看吧

 6.2 口令文件

口令文件其实就是/etc文件夹下的passwd文件,但处于安全性的考虑,我们无法直接读取它。就是通过直接限制权限的方式对其进行保护,passwd文件具体权限如下:

-rw-r--r-- 1 root root

可以看到只有root用户具有读写权限,与root同组的用户与其他用户仅具有读权限。

不过为了解决以上问题,Linux中给出了一系列数据结构与函数帮助我们操纵口令文件,首先是关键数据结构,定义位于/include/pwd.h

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.  */
};

给出用户登录名与数值用户ID后,通过以下两个函数就能获得passwd结构体,该结构体中包含有我们需要的信息。

#include <pwd.h>
extern struct passwd *getpwuid (__uid_t __uid);
extern struct passwd *getpwnam (const char *__name);

getpwuid函数由ls程序使用。getpwnam函数由login程序使用。passwd结构通常是函数内部的静态变量,只要调用任一相关函数,其内容就会被重写。

以上两个函数仅能查看某一个用户的口令信息,但如果不知道其他用户的登录名或数值ID,则无法获得这些信息。因此Linux中又给出了以下三个函数来查看整个口令文件。

#include <pwd.h>
extern struct passwd *getpwent (void); //若成功,返回指针,指向口令文件中的下一个记录项。第一次调用时,它打开所使用的各个文件。
extern void setpwent (void); //回到口令文件开头
extern void endpwent (void); //关闭口令文件

6.3节中所提到的阴影口令文件感觉与口令文件的内容并没有多大的差距,在此就先不深入研究了,以后遇到了再说。

6.4组文件

还是相同的思路,如果用户程序想访问组相关信息,这些信息虽然存放在/etc/group中,但还是由于权限的限制导致一般的用户无法直接访问这一问题。Linux中给出的方法是通过相关的函数与数据结构进行访问,首先来看关键数据结构。

struct group{char *gr_name;		/* Group name.	*/char *gr_passwd;		/* Password.	*/__gid_t gr_gid;		/* Group ID.	*/char **gr_mem;		/* Member list.	*/};

通过组名与数值ID可以获得这一数据结构。

#include <grp.h>
extern struct group *getgrgid (__gid_t __gid);
extern struct group *getgrnam (const char *__name);

搜索整个口令文件则需要以下三个函数,思路也是一样的。

#include <grp.h>
extern void setgrent (void);
extern void endgrent (void);
extern struct group *getgrent (void);

6.5 附属组

引入附属组的一个原因是:一个用户会参与多个项目,因此也就要同时属于多个组。为了解决上述问题,4.2BSD引入了附属组的概念,用户不再简单的属于一个组,也可以属于多至16个另外的组。

用户程序可通过以下函数获取和设置附属组ID。

extern int getgrouplist (const char *__user, __gid_t __group,__gid_t *__groups, int *__ngroups);
extern int setgroups (size_t __n, const __gid_t *__groups) __THROW;
extern int initgroups (const char *__user, __gid_t __group);

其中setgroups需要超级用户权限调用,而由于initgroups需要调用setgroups,因此initgroups也同样只有超级用户才能调用。

6.7其他数据文件

除了上面提到的口令文件和组文件,Linux还有多个具有类似概念的文件。书中给出了一个表对上述内容进行总结。

说明数据文件头文件结构附加的减搜索函数
口令/etc/passwd<pwd.h>passwdgetpwnam/getpwuid
/etc/group<grp.h>groupgetgrnam/getgrgid
阴影口令/etc/shadow<shadow.h>spwdgetspnam
主机/etc/hosts<netdb.h>hostnetgetnameinfo/getaddrinfo
网络/etc/networks<netdb.h>netentgetnetbyname/getnetbyaddr
协议/etc/protocols<netdb.h>protonetgetprotobyname/getprotobynumber
服务/etc/services<netdb.h>serventgetserbyname/getserbyport

6.8登录账户记录

Linux通过“/var/run/utmp”对当前登录到系统的各个用户进行记录;通过“/var/log/wtmp”文件跟踪各个登录和注销事件。以上两个文件是二进制文件,不能直接打开。

Linux通过以下几个函数与数据结构对以上两个文件进行修改。首先来看看关键数据结构,定义位于/usr/include/x86_64-linux-gnu/bits/utmp.h中

struct utmp
{short int ut_type;		/* Type of login.  */pid_t ut_pid;			/* Process ID of login process.  */char ut_line[UT_LINESIZE];	/* Devicename.  */char ut_id[4];		/* Inittab ID.  */char ut_user[UT_NAMESIZE];	/* Username.  */char ut_host[UT_HOSTSIZE];	/* Hostname for remote login.  */struct exit_status ut_exit;	/* Exit status of a process markedas DEAD_PROCESS.  */
/* The ut_session and ut_tv fields must be the same size when compiled32- and 64-bit.  This allows data files and shared memory to beshared between 32- and 64-bit applications.  */
#ifdef __WORDSIZE_TIME64_COMPAT32int32_t ut_session;		/* Session ID, used for windowing.  */struct{int32_t tv_sec;		/* Seconds.  */int32_t tv_usec;		/* Microseconds.  */} ut_tv;			/* Time entry was made.  */
#elselong int ut_session;		/* Session ID, used for windowing.  */struct timeval ut_tv;		/* Time entry was made.  */
#endifint32_t ut_addr_v6[4];	/* Internet address of remote host.  */char __glibc_reserved[20];		/* Reserved for future use.  */
};

再来看看相关函数:

extern void login (const struct utmp *__entry) __THROW;

登录时,login程序填写此类型结构,然后将其写入到utmp文件中,同时也将其添写到wtmp文件中。通过login函数的参数也可以验证这一点。

注销时,init进程将utmp文件中相应的记录擦除,并将一个新记录添写到wtmp文件中。

6.9 系统标识

POSIX.1 定义了uname函数,它返回与主机和操作系统有关的信息。定义位于/usr/include/x86_64-linux-gnu/sys/utsname.h。

extern int uname (struct utsname *__name) __THROW; //__name即是输入参数也是输出参数。若程序运行成功返回非负值,若出错返回-1。

参数定义如下:

struct utsname{/* Name of the implementation of the operating system.  */char sysname[_UTSNAME_SYSNAME_LENGTH];/* Name of this node on the network.  */char nodename[_UTSNAME_NODENAME_LENGTH];/* Current release level of this implementation.  */char release[_UTSNAME_RELEASE_LENGTH];/* Current version level of this release.  */char version[_UTSNAME_VERSION_LENGTH];/* Name of the hardware type the system is running on.  */char machine[_UTSNAME_MACHINE_LENGTH];#if _UTSNAME_DOMAIN_LENGTH - 0/* Name of the domain of this node on the network.  */
# ifdef __USE_GNUchar domainname[_UTSNAME_DOMAIN_LENGTH];
# elsechar __domainname[_UTSNAME_DOMAIN_LENGTH];
# endif
#endif};

utsname结构体中的信息通常可用uname命令打印。我的机器上uname的返回结果非常简单

Linux

仅此而已,再无其他。

还有一个返回主机名的函数,该名字通常就是TCP/IP网络上主机的名字。

extern int gethostname (char *__name, size_t __len) __THROW __nonnull ((1));

其中name即是输入参数也是输出参数。

hostname命令可用来获取和设置主机名。主机名通常在系统自举时设置,它由/etc/rc或init取自一个启动文件。

6.10 时间和日期例程

由UNIX内核提供的基本时间服务是计算自协调世界时(Coordinated Universal Time,UTC)公元1970年1月1日00:00:00这一特定时间以来经过的秒数。这一秒数通过以下函数获得:

#include <time.h>
extern time_t time (time_t *__timer) __THROW;

通过clock_gettime同样可以获得这一秒数,但其时间精度更高:

#include <time.h>
extern int clock_gettime (clockid_t __clock_id, struct timespec *__tp) __THROW;

time与clock_gettime函数的结果可以直接相互转化。

time_t类型的参数可以通过gmtime函数转化为协调统一时间的年、月、日、时、分、秒、周日分解。这一格式的时间通过以下结构体表示。

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
};

这一类型需要通过strftime转化为字符串模式并输出。

extern size_t strftime (char *__restrict __s, size_t __maxsize,const char *__restrict __format,const struct tm *__restrict __tp) __THROW;

一个格式化的时间字符串可通过以下函数转化为结构体struct tm。

extern char *strptime (const char *__restrict __s,const char *__restrict __fmt, struct tm *__tp)__THROW;

struct tm结构体又可以通过mktime函数转化为time_t类型参数。

extern time_t mktime (struct tm *__tp) __THROW;

最后给大家附上各时间结构体之间的转化关系。



这篇关于APUE读书笔记-第六章 系统数据文件和信息的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1095267

相关文章

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)

《使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)》PPT是一种高效的信息展示工具,广泛应用于教育、商务和设计等多个领域,PPT文档中常常包含丰富的图片内容,这些图片不仅提升了... 目录一、引言二、环境与工具三、python 提取PPT背景图片3.1 提取幻灯片背景图片3.2 提取

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文

利用Python快速搭建Markdown笔记发布系统

《利用Python快速搭建Markdown笔记发布系统》这篇文章主要为大家详细介绍了使用Python生态的成熟工具,在30分钟内搭建一个支持Markdown渲染、分类标签、全文搜索的私有化知识发布系统... 目录引言:为什么要自建知识博客一、技术选型:极简主义开发栈二、系统架构设计三、核心代码实现(分步解析

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用

Linux系统之dns域名解析全过程

《Linux系统之dns域名解析全过程》:本文主要介绍Linux系统之dns域名解析全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、dns域名解析介绍1、DNS核心概念1.1 区域 zone1.2 记录 record二、DNS服务的配置1、正向解析的配置

一文详解SQL Server如何跟踪自动统计信息更新

《一文详解SQLServer如何跟踪自动统计信息更新》SQLServer数据库中,我们都清楚统计信息对于优化器来说非常重要,所以本文就来和大家简单聊一聊SQLServer如何跟踪自动统计信息更新吧... SQL Server数据库中,我们都清楚统计信息对于优化器来说非常重要。一般情况下,我们会开启"自动更新

Linux系统中配置静态IP地址的详细步骤

《Linux系统中配置静态IP地址的详细步骤》本文详细介绍了在Linux系统中配置静态IP地址的五个步骤,包括打开终端、编辑网络配置文件、配置IP地址、保存并重启网络服务,这对于系统管理员和新手都极具... 目录步骤一:打开终端步骤二:编辑网络配置文件步骤三:配置静态IP地址步骤四:保存并关闭文件步骤五:重