还是按照问题一步一步的展开
1. who能做什么
2. who怎样工作的
3. 如何实现who
1. who能做什么
在linux中who就是显示谁在使用系统。
2. who怎样工作的:
直接man who,可以看到如下的描述
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.
可以看到who是从utmp获取信息的, 收索联机帮助 寻找utmp
man -k utmp
utmp (5) - login records
直接man 5 utmp
The file is a sequence of utmp structures, declared as follows in(note that this is only one of several definitions around; details depend on the version of libc):... ...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 (1 */ /* 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
可以看到数据都放在utmp中.继续往下可以看到文件的位置信息
FILES /var/run/utmp /var/log/wtmp
3. 如何实现who
到这里基本上就可以开始用伪代码编写了:
伪代码如下:
打开utmp
读取用户记录
显示用户记录
关闭utmp
因为这次读取是直接读取数据块,一行一行(fgets)和一个字符一个字符(getchar)的读取都不合适,所以选用read函数。
第一步自然是打开utmp,这个文件的路径在哪里呢, 头文件一般都是放在/USR/INCLUDE/下的,果然在头文件中找到路径的定义:
/* Compatibility names for the strings of the canonical file names. */#define UTMP_FILE _PATH_UTMP#define UTMP_FILENAME _PATH_UTMP#define WTMP_FILE _PATH_WTMP#define WTMP_FILENAME _PATH_WTMP
可以随便选一个,我们就选第一个作为路径。按照伪代码编写如下
#include#include #include #include void ShowRecord(struct utmp*);int main(int ac, char* av[]){ struct utmp record; int recordSize = sizeof(record); int utmpFd; //打开utmp utmpFd = open(UTMP_FILE,O_RDONLY); if(-1 == utmpFd) { perror(UTMP_FILE); return -1; } //读取用户记录 while (read(utmpFd,&record,recordSize) == recordSize) { //显示用户记录 ShowRecord(&record); } //关闭utmp close(utmpFd); return 0;}void ShowRecord(struct utmp* pRecord){ printf("%-8.8s\n",pRecord->ut_name); printf("%-8.8s\n",pRecord->ut_line); printf("%-8.8d\n",pRecord->ut_time); printf("\n");}
运行结果:
jerry@ubuntu:~/work/chapter01$ ./test reboot ~ 1492427813LOGIN tty1 1492427835runlevel~ 1492427839jerry tty7 1492427909jerry@ubuntu:~/work/chapter01$
数据读出来了,就是显示格式需要再调整。继续进行优化如下问题,今天就到这里
1. 格式排版问题
2. 时间显示问题