System Data Files and Infomation
1. Password File
UNIX中的密码为passwd
结构体, 该struct至少包含以下field:
struct passwd { |
对于绝大多数UNIX系统, /etc/passwd
会作为密码库, 每一行包含一个passwd, 每一个field由:
分割, 例如:
root:x:0:0:root:/root:/bin/bash |
- root用户为superuser, 因为UID为0
- 曾经的UNIX会将密码单向hash的密码放在
/etc/passwd
, 但现代UNIX会用一个placeholder替代, 真正的密码被放在shadow database中, 只有特定权限才能访问. - 每个用户都有一个shell用于执行命令, 默认为
/bin/sh
. 若为/dev/null
, 任何输入都会被抛弃, 因此无法执行任何命令. - nobody用户占用最后一位UID和GID: 65534. 该用户没有任何权限, 只能访问一些普通文件, 一般服务于FTP或HTTP远程访问的用户.
- 部分UNIX系统提供了
finger
命令来查看更多的信息:$ finger -p root
Login: root Name: System Administrator
Directory: /var/root Shell: /bin/sh
Last login Wed Jul 31 16:26 (EDT) on console
No Mail. - 部分UNIX系统提供
vipw
命令, 允许administrator来修改password文件.
以下函数用于获取passwd
的entry:
/** |
需要注意的是, getpwuid()
返回的passwd
指针可能会被后续getpwent()
, getpwnam()
, 或getpwuid()
重写, 导致内部数据无效化, 也会因当前线程中止而无效化.
2. Shadow Passwords
加密后的密码存放在shadow password file中. 由于加密算法是单向的, 因此即使知道加密后的hash值也无法知道密码. shadow password file中包含spwd struct
:
struct spwd { |
该文件只能被特定程序访问, 如login()
, passwd()
, 和设置了set-user-ID
且文件所有者为root
的可执行文件; password file可被任何用户访问.
/** |
3. Group File
UNIX使用group划分不同user, 多个user可属于同一group. 由于文件权限分为三部分, 因此可通过设置group权限来控制特定user群体的权限.
UNIX的group信息存放于group file, POSIX.1称为group database. 该文件通常位于/etc/group
, 包含一个或多个group struct
:
struct group { |
POSIX也提供函数访问group file.
/** |
需要注意的是, getgrgid()
返回的指向group struct
的指针会被后续getgrent()
, getgrgid()
, 或getgrnam()
无效化; 中止当前线程也会令该指针无效化.
4. Supplementary Group IDs
UNIX设计之初并没有supplementary group, 一个user只属于一个group, 用户需要其他group的权限时, 则需调用newgrp()
改变当前user的real group ID. Kernel检查进程是否拥有文件访问权限时, 只需对比进程的EGID与文件的GID. 执行完毕后, 用户需再次调用newgrp()
切换回原本的group.
但user和group之间的关系不应为多对一, 而是多对多, 每个group可包含多个user, user也可处于多个group中. 4.2BSD添加了supplementary group ID. user仍拥有一个GID, 称为primary group ID, 但还拥有多个supplementary group ID. Kernel检查进程是否拥有文件的访问权限时, 若进程的EGID不匹配, 则对比supplementary group ID.
/** |
5. Other Data Files
除了password file和group file, UNIX系统还包括其他文件: network service(/etc/services
), internet protocols(/etc/protocols
). UNIX提供以下函数来访问这些文件:
get
: read the next entry of file.set
: open file if not already open, and rewind the fileend
: close the data file
Description | File Localtion | Header | Structure | Additional keyed lookup functions |
---|---|---|---|---|
password | /etc/passwd | <pwd.h> | passws | getpwnam, getpwuid |
groups | /etc/group | <grp.h> | group | getgrnam, getgrgid |
shadow | /etc/shadow | <shadow.h> | spwd | getspnam |
hosts | /etc/hosts | <netdb.h> | hostent | getnameinfo, getaddrinfo |
networks | /etc.networks | <netdb.h> | netent | getnetbyname, getnetbyaddr |
protocols | /etc/protocols | <netdb.h> | protoent | getprotobyname, getprotobynumber |
services | /etc/services | <netdb.h> | servent | getservbyname, getservbyport |
6. Login Accounting
UNIX提供了两个data file:
- utmp: 记录所有当前登录的用户
- wtmp: 记录所有登录和登出动作
struct utmp { |
用户登录时, login
程序会向utmp
和wtmp
写入一个utmp struct
; 用户登出时, init
进程从utmp
中删除该用户, 并向wtmp
写入一个新的utmp struct
, 用null username表示用户在关联terminal上注销.
7. System Identification
struct utsname { |
由于历史原因, nodename
并不能表示TCP/IP上的hostname, 如需则调用gethostname()
.
/** |
8. Time and Date Routines
UNIX使用UTC(Coordinated Universal Time)存储时间信息, 数据类型为time_t, 并会自动处理time zone, daylight saving time等问题.
/** |
除了time_t
, 其他类型也可表示时间戳:
8.1 timespec struct
struct timespec { |
- 任何物理时钟都存在偏差, 计算机运行的越久, 与实际时间的偏差越大, 因此需要管理员手动修改, 或NTP纠正,
CLOCK_REALTIME
则表示最接近实际的时间; 但该时间可能不连续, 例如, 第一次获取的时间小于第二次获取的时间, 给人一种时间回溯的感觉, 因此引入CLOCK_MONOTONIC
, 该时间无法被修改, 可用于计算两个事件之间的时间差. - UNIX支持多进程, 但进程并发受限于很多因素(如CPU数量), 因此进程可能处于等待队列, 计算一个程序的实际性能时, 我们只想知道程序的实际运行时间, 可使用
CLOCK_PROCESS_CPUTIME_ID
8.2 tm structure
struct tm { |
Conversion sepcifier for strftime()
:
Format | Description | Example |
---|---|---|
%a | abbreviated weekday name | Thu |
%A | full weekday name | Thursday |
%b | abbreviated month name | Jan |
%B | full month name | January |
%c | date and time | Thu Jan 19 21:24:52 2012 |
%C | year/100: [00–99] | 20 |
%d | day of the month: [01–31] | 19 |
%D | date [MM/DD/YY] | 01/19/12 |
%e | day of month (single digit preceded by space) [1–31] | 19 |
%F | ISO 8601 date format [YYYY–MM–DD] | 2012-01-19 |
%g | last two digits of ISO 8601 week-based year [00–99] | 12 |
%G | ISO 8601 week-based year | 2012 |
%h | same as %b | Jan |
%H | hour of the day (24-hour format): [00–23] | 21 |
%I | hour of the day (12-hour format): [01–12] | 09 |
%j | day of the year: [001–366] | 019 |
%m | month: [01–12] | 01 |
%M | minute: [00–59] | 24 |
%n | newline character | |
%p | AM/PM | PM |
%r | locale’s time (12-hour format) | 09:24:52 PM |
%R | same as %H:%M | 21:24 |
%S | second: [00–60] | 52 |
%t | horizontal tab character | |
%T | same as %H:%M:%S | 21:24:52 |
%u | ISO 8601 weekday [Monday = 1, 1–7] | 4 |
%U | Sunday week number: [00–53] | 03 |
%V | ISO 8601 week number: [01–53] | 03 |
%w | weekday: [0 = Sunday, 0–6] | 4 |
%W | Monday week number: [00–53] | 03 |
%x | locale’s date 01/19/ | 12 |
%X | locale’s time 21:24: | 52 |
%y | last two digits of year: [00–99] | 12 |
%Y | year | 2012 |
%z | offset from UTC in ISO 8601 format | -0500 |
%Z | time zone name | EST |
%% | translates to a percent sign | % |