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

相关文章

CSS3 最强二维布局系统之Grid 网格布局

《CSS3最强二维布局系统之Grid网格布局》CS3的Grid网格布局是目前最强的二维布局系统,可以同时对列和行进行处理,将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局,本文介... 深入学习 css3 目前最强大的布局系统 Grid 网格布局Grid 网格布局的基本认识Grid 网

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

在不同系统间迁移Python程序的方法与教程

《在不同系统间迁移Python程序的方法与教程》本文介绍了几种将Windows上编写的Python程序迁移到Linux服务器上的方法,包括使用虚拟环境和依赖冻结、容器化技术(如Docker)、使用An... 目录使用虚拟环境和依赖冻结1. 创建虚拟环境2. 冻结依赖使用容器化技术(如 docker)1. 创

CentOS系统Maven安装教程分享

《CentOS系统Maven安装教程分享》本文介绍了如何在CentOS系统中安装Maven,并提供了一个简单的实际应用案例,安装Maven需要先安装Java和设置环境变量,Maven可以自动管理项目的... 目录准备工作下载并安装Maven常见问题及解决方法实际应用案例总结Maven是一个流行的项目管理工具

C#实现系统信息监控与获取功能

《C#实现系统信息监控与获取功能》在C#开发的众多应用场景中,获取系统信息以及监控用户操作有着广泛的用途,比如在系统性能优化工具中,需要实时读取CPU、GPU资源信息,本文将详细介绍如何使用C#来实现... 目录前言一、C# 监控键盘1. 原理与实现思路2. 代码实现二、读取 CPU、GPU 资源信息1.

在C#中获取端口号与系统信息的高效实践

《在C#中获取端口号与系统信息的高效实践》在现代软件开发中,尤其是系统管理、运维、监控和性能优化等场景中,了解计算机硬件和网络的状态至关重要,C#作为一种广泛应用的编程语言,提供了丰富的API来帮助开... 目录引言1. 获取端口号信息1.1 获取活动的 TCP 和 UDP 连接说明:应用场景:2. 获取硬

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

2.1/5.1和7.1声道系统有什么区别? 音频声道的专业知识科普

《2.1/5.1和7.1声道系统有什么区别?音频声道的专业知识科普》当设置环绕声系统时,会遇到2.1、5.1、7.1、7.1.2、9.1等数字,当一遍又一遍地看到它们时,可能想知道它们是什... 想要把智能电视自带的音响升级成专业级的家庭影院系统吗?那么你将面临一个重要的选择——使用 2.1、5.1 还是

C#实现获取电脑中的端口号和硬件信息

《C#实现获取电脑中的端口号和硬件信息》这篇文章主要为大家详细介绍了C#实现获取电脑中的端口号和硬件信息的相关方法,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 我们经常在使用一个串口软件的时候,发现软件中的端口号并不是普通的COM1,而是带有硬件信息的。那么如果我们使用C#编写软件时候,如