標籤:unix環境進階編程 linux shell
思路:在unix系統中有一個名為utmp的檔案,裡面存著當前登入到系統中使用者的資訊。utmp這個檔案裡面儲存的是結構數組,數組元素是utmp類型的結構。實現who命令,只要依次從utmp檔案中讀出utmp類型的結構體,然後通過合適的方式將它顯示出來即可。如果每一次只從檔案裡面讀一個結構體資料,那麼每一個結構體都要進行依次系統調用。而又因為系統調用比較耗時(涉及到使用者態到核心態的切換),所以這樣會造成程式低效。我們使用緩衝技術,每次從檔案中讀若干結構體資料到記憶體中,當這些資料都已經顯示在終端後,我們再從檔案中讀資料,這樣能有效提高程式的效率。
代碼:
utmplib.c
#include <fcntl.h>#include <sys/types.h>#include <utmp.h>#define NRECS 16#define UTSIZE (sizeof(struct utmp))#define UTNULL ((struct utmp *)NULL)static char utmp_buffer[NRECS * UTSIZE];static int utmp_num;static int cur_num;static int utmp_fd = -1;int utmp_open(char * filename){ utmp_fd = open(filename,O_RDONLY); cur_num = 0; utmp_num = 0; return utmp_fd;}struct utmp * utmp_next(){ struct utmp * next; if(utmp_fd == -1) return UTNULL; if(cur_num == utmp_num && utmp_reload() == 0) return UTNULL; next = (struct utmp *)&utmp_buffer[UTSIZE*cur_num]; cur_num++; return next;}int utmp_reload(){ int len = read(utmp_fd,utmp_buffer,UTSIZE*NRECS); utmp_num = len / UTSIZE; cur_num = 0; return utmp_num;}void utmp_close(){ if(utmp_fd != -1) close(utmp_fd);
who.c
#include "utmplib.c"#include <sys/types.h>#include <utmp.h>#include <fcntl.h>#include <time.h>void show_info(struct utmp *);void showtime(time_t);int main(){printf("%s",UTMP_FILE);struct utmp * utmp_buffer;int fd;if((fd = utmp_open(UTMP_FILE)) == -1)return -1;//utmp_reload();while((utmp_buffer = utmp_next()) != UTNULL)show_info(utmp_buffer);utmp_close();return 0;}void show_info(struct utmp * buffer){if(buffer->ut_type != USER_PROCESS)//utmp結構中有一個ut_type成員,當其為USER_PROCESS時,表明這是一個已經登陸的使用者return;printf("%-8.8s",buffer->ut_name);printf(" ");printf("%-8.8s",buffer->ut_line);printf(" ");showtime(buffer->ut_time);#ifdef SHOWHOSTif(buffer->ut_host[0] != '\0')printf("(%s)",buffer->ut_host);#endifprintf("\n");}void showtime(time_t time){char * cp;cp = ctime(&time);printf("%12.12s",cp+4);}
自己動手寫shell命令之who