本文的代码出自《Unix/Linux编程实践教程》,但也包含作者的实践经验和收获,作者的主要的目的是记录自己的学习过程,不喜勿喷。
如果这篇文章也帮到了正在阅读的你,那我感到非常荣幸。who命令原理:读取/var/run/utmp文件内容,让后显示。
涉及到的系统调用:open,read,close,write(没有用到write,但是顺道mark一下)
1. open 打开name指定的文件
#include<fcntl.h>
int fd = open(char *name,int how)
name:文件名
how: O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(可读可写)
成功,返回文件描述符
错误,返回-1
2. read 将文件内容读到内存
#include<unistd.h>
size_t numread = read(int fd,void *buf,size_t qty)
fd: open返回的文件描述符
buf: 用来存放数据的目的缓冲区。eg. char buf[SIZE]
qty:要读取的字节数
成功,返回读取字节数
失败,返回-1
3. write 将内存中数据写到文件中
#include <unistd.h>
size_t result = write(int fd, void * buf ,size_t amt)
fd: open返回的文件描述符
buf: 内存中的数据
amt: 要写的字节数
成功,返回写入的字节数
失败,返回-1
4. close 关闭文件
#include<unistd.h>
int result = close(int fd)
fd: open返回的文件描述符
成功,返回0
失败,返回-1
以上系统调用的一般用法为:
1.open打开指定文件,并得到文件描述符
2.read或write进行读写操作,可以多次读取,在文件关闭之后,文件指针才会初始化(在做缓存机制练习时,因为忽略这个问题,对read返回0非常郁闷不解)
3.文件读写(自动或人为),close关闭文件。
实践收获:
1.缓存机制的运用
实例中的缓存为一个可以容纳16个结构体的字符数组。要注意的是,数组元素并不是一个结构体,而是结构体中的各个成员。
每个结构体在数组中的相对位置为sizeof(struct utmp),取出结构体的方式即是获得结构体第一个成员在数组中的位置,然后进行类型转换(struct utmp *)。
而我最开始想到的方式是 将每个数组元素定义为一个结构体,待实现。
2.格式输出:
1)printf("% - 8.8s",stringname)。 %m.ns中,m表示要显示的位数,n表示输出字符串的位数,m>n时,左边补空字符,凑齐m位输出。
m<n时,输出按%n.ns的格式输出。'—'表示左对齐。(who3.c中有运用)
2)printf("%02d",numeric)。'2'表示输出两位,'0'表示不足2位用0补上,否则为用' '补齐。(who3.c应用)
3.utmp结构体
utmp结构体在/usr/include/bits/utmp.h中定义,但要include<utmp.h>,不要include<bits/utmp.h>。
实践中所用成员分别为
1)short int ut_type 登陆类型,有10个值,本实例中用的#define USER_PROCESS 7,表示是一个一般的用户程序登陆。
当ut_type为其他值时,ut_user可能为空,此项可以避免输出时的空项。
2)char ut_lint[UT_LINESIZE] 设备名,如:tty,pst
3)char ut_user[UT_NAMESIZE] 登陆的用户名
4)char ut_host[UT_HOSTSIZE] 远程登陆的用户名
4. /usr/include/paths.h 中有非常多的关于 特殊文件 路径的宏定义。本实例中,#define UTMP_PATH /var/run/utmp
5.#ifdef SHOWHOST
printf(ut_host)
#endif
如果定义了SHOWHOST,就打印ut_host。(在who3.c中有应用)
6.man -k utmp 在man中查找有关键词utmp的entries.
7.info coreutils "who invocation" --vi-key 在info中查找coreutils中的who命令,并用vi模式打开info(即可用vi命令在info中进行查找)
如有错误,请留言,谢谢。
代码实现:(站在巨人的肩膀上)
实现平台:CentOS 6.4 32bit gcc4.4.7
http://download.csdn.net/detail/heiheihei8809/7681343