who 命令的实现
who 命令显示 当前已经登录的用户
查看连接帮助: man who
who(1) 表示who的小结编号。
NAME 包含命令的名字以及对这个命令的简短说明
SYNOPSYS 给出命令的用法说明,命令格式,参数列表等
DESCRIPTION 关于命令功能的详细阐述,描述命令的所有功能,命令的权威解释。
AUTHOR 命令的作者
REPORTING BUGS 命令的残留BUG
COPYRIGHT 版权
SEE ALSO 参阅,这个命令相关的其他主题。
从 man who :
DESCRIPTION:
If FILE is not specified, use /var/run/utmp. /var/log/wtmp as FILE is common. If ARG1 ARG2 given, -m presumed: `am i' or `mom likes' are usual.
可以看到已登录信息是存放在 /var/run/utmp 文件中的
联机搜素帮助: man -k utmp
endutent (3) - access utmp file entries
endutxent (3) - access utmp file entries
getutent (3) - access utmp file entries
getutent_r (3) - access utmp file entries
getutid (3) - access utmp file entries
getutid_r (3) - access utmp file entries
getutline (3) - access utmp file entries
getutline_r (3) - access utmp file entries
getutmp (3) - copy utmp structure to utmpx, and vice versa
getutmpx (3) - copy utmp structure to utmpx, and vice versa
getutxent (3) - access utmp file entries
getutxid (3) - access utmp file entries
getutxline (3) - access utmp file entries
login (3) - write utmp and wtmp entries
logout (3) - write utmp and wtmp entries
pututline (3) - access utmp file entries
pututxline (3) - access utmp file entries
sessreg (1) - manage utmp/wtmp entries for non-init clients
setutent (3) - access utmp file entries
setutxent (3) - access utmp file entries
utmp (5) - login records
utmpname (3) - access utmp file entries
utmpx (5) - login records
utmpxname (3) - access utmp file entries
可以看到有关 用户登录的文件存放在 utmp (5) - login records 中。
联机搜索:man 5 utmp
NAME
utmp, wtmp - login records
SYNOPSIS
#include <utmp.h>
DESCRIPTION
The utmp file allows one to discover information about who is currently using the system. There may be more users currently using the system,
because not all programs use utmp logging.
可以看到命令 who 会去读 utmp 这个文件,utmp 中保存的是 utmp 这个数据结构,utmp 结构类型在 utmp.h 定义。
需要去 /usr/include/ 目录下面寻找相应的头文件 。
可以直接 more /usr/include/utmp.h 没有看到 utmp 结构的定义
man 5 utmp 可以得到:
struct utmp {
short ut_type; /* Type of record */
pid_t ut_pid; /* PID of login process */
char ut_line[UT_LINESIZE]; /* Device name of tty - "/dev/" */
char ut_id[4]; /* Terminal name suffix, or inittab(5) ID */
char ut_user[UT_NAMESIZE]; /* Username */
char ut_host[UT_HOSTSIZE]; /* Hostname for remote login, or kernel version for run-level messages */
struct exit_status ut_exit; /* Exit status of a process marked as DEAD_PROCESS; not used by Linux init(8) */
/* The ut_session and ut_tv fields must be the same size when
compiled 32- and 64-bit. This allows data files and shared
memory to be shared between 32- and 64-bit applications. */
#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
int32_t ut_session; /* Session ID (getsid(2)),
used for windowing */
struct {
int32_t tv_sec; /* Seconds */
int32_t tv_usec; /* Microseconds */
} ut_tv; /* Time entry was made */
#else
long ut_session; /* Session ID */
struct timeval ut_tv; /* Time entry was made */
#endif
int32_t ut_addr_v6[4]; /* Internet address of remote
host; IPv4 address uses
just ut_addr_v6[0] */
char __unused[20]; /* Reserved for future use */
};
/* Backwards compatibility hacks */
#define ut_name ut_user
#ifndef _NO_UT_TIME
#define ut_time ut_tv.tv_sec
#endif
#define ut_xtime ut_tv.tv_sec
#define ut_addr ut_addr_v6[0]
可以看到有
ut_type 用户类型
ut_pid 用户PID
ut_line[UT_LINESIZE] 设备名 用户终端类型
ut_id[4] 用户ID
ut_user[UT_NAMESIZE] 登录名
ut_host[UT_HOSTSIZE] 终端名
ut_time 用户登录时间
who 的工作过程:
1.从数据库中读取数据结构
2.将结构中的信息以合适的形式读取显示出来。
如何从文件中读取数据结构
搜索联机帮助:man -k file | grep read
__freadable (3) - interfaces to stdio FILE structure
__freading (3) - interfaces to stdio FILE structure
_llseek (2) - reposition read/write file offset
eventfd_read (3) - create a file descriptor for event notification
fc-cat (1) - read font information cache files
fgetwc (3) - read a wide character from a FILE stream
fgetws (3) - read a wide-character string from a FILE stream
fts_read (3) - traverse a file hierarchy
getwc (3) - read a wide character from a FILE stream
llseek (2) - reposition read/write file offset
lseek (2) - reposition read/write file offset
lseek64 (3) - reposition 64-bit read/write file offset
pppdump (8) - convert PPP record file to readable format
pread (2) - read from or write to a file descriptor at a give...
pread64 (2) - read from or write to a file descriptor at a give...
pwrite (2) - read from or write to a file descriptor at a give...
pwrite64 (2) - read from or write to a file descriptor at a give...
read (2) - read from a file descriptor
readahead (2) - perform file readahead into page cache
readelf (1) - Displays information about ELF files.
readlinkat (2) - read value of a symbolic link relative to a direc...
readprofile (1) - a tool to read kernel profiling information
tee (1) - read from standard input and write to standard ou...
ureadahead (8) - Read files in advance during boot
可以看到最有可能的是 read (2) - read from a file descriptor
man 2 read
SYNOPSIS
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
DESCRIPTION
read() attempts to read up to count bytes from file descriptor fd into the buffer starting at buf.
If count is zero, read() returns zero and has no other results. If count is greater than SSIZE_MAX, the result is unspecified.
可以看到这个 read 的系统调用命令从文件描述符 fd 指向的文件中将数据读入一个缓冲区*buf,指定读取的字节数 count
如何得到这个文件描述符 fd 呢 在联机帮助中有
SEE ALSO
close(2), fcntl(2), ioctl(2), lseek(2), open(2), pread(2), read‐
dir(2), readlink(2), readv(2), select(2), write(2), fread(3)
man 2 open
SYNOPSIS
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
DESCRIPTION
Given a pathname for a file, open() returns a file descriptor, a
small, non-negative integer for use in subsequent system calls
(read(2), write(2), lseek(2), fcntl(2), etc.). The file descrip‐
tor returned by a successful call will be the lowest-numbered file
descriptor not currently open for the process.
可以看到:Given a pathname for a file, open() returns a file descriptor

浙公网安备 33010602011771号