实现了linux中w ho 命令,采用了缓冲机制,一次从utmp文件中读取16条数据,这样可以大大提高性能。
下面是代码,采用了缓冲机制:
1 /*
2 * what is diffient to who1 is that we add a buffer area in who2.c.
3 * In this way, the efferency is improved .
4 */
5 #include <stdio.h>
6 #include <utmp.h>
7 #include <fcntl.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <time.h>
11
12 #define SHOWHOST //include remote machine on output
13
14 //-------------------------------------------------------------------------
15 #define NRECS 16
16 #define NULLUT ((struct utmp *)NULL)
17 #define UTSIZE (sizeof(struct utmp))
18
19 static char utmpbuf[NRECS * UTSIZE]; //storage
20 static int num_recs; //num stored
21 static int cur_rec; //next to go
22 static int fd_utmp = -1; //read from
23
24 int utmp_open(char *filename)
25 {
26 fd_utmp = open(filename, O_RDONLY);
27 cur_rec = num_recs = 0;
28 return fd_utmp;
29 }
30
31 int utmp_reload()
32 {
33 int amt_read;
34 amt_read = read(fd_utmp, utmpbuf, NRECS * UTSIZE);
35 num_recs = amt_read/UTSIZE; //how many did we get?
36 cur_rec = 0; //reset pointer
37
38 return num_recs;
39 }
40
41 struct utmp * utmp_next()
42 {
43 struct utmp * recp;
44 if( fd_utmp == -1) return NULLUT;
45
46 if(cur_rec == num_recs && utmp_reload() == 0) return NULLUT;
47
48 recp = (struct utmp *) &utmpbuf[cur_rec * UTSIZE];
49 cur_rec++;
50 return recp;
51 }
52
53 void utmp_close()
54 {
55 if(fd_utmp != -1) close(fd_utmp); //don't close if not open
56 }
57
58 //-------------------------------------------------------------------------
59
60 void show_info(struct utmp *);
61 void showtime(long timeval);
62
63 int main()
64 {
65 struct utmp * utbufp; //holds pointer to next rec
66 struct utmp * utmp_next(); //return pointer to next
67
68 if(utmp_open(UTMP_FILE) == -1)
69 {
70 perror(UTMP_FILE);
71 exit(1);
72 }
73 while ( (utbufp = utmp_next() ) != ((struct utmp *) NULL) )
74 show_info(utbufp);
75
76 utmp_close();
77
78 return 0;
79
80 }
81
82 /*
83 * display contents of the utmp struct
84 */
85 void show_info( struct utmp * utbufp)
86 {
87 /*
88 * remove the blank record
89 * the entry ut_type in struct utmp indicate the types
90 * USER_PROCESS is the auser process
91 */
92 if(utbufp-> ut_type != USER_PROCESS) return;
93
94 printf("% -8.8s", utbufp->ut_name);
95 printf(" ");
96 printf("% -12.12s", utbufp->ut_line);
97 printf(" ");
98 //printf("%101d", utbufp->ut_time);
99 showtime(utbufp->ut_time);
100 printf(" ");
101 #ifdef SHOWHOST
102 printf("(%s)", utbufp->ut_host);
103 #endif
104 printf("\n");
105 }
106
107 void showtime(long timeval)
108 {
109 /*
110 * display time
111 */
112 char *cp;
113 cp = ctime(&timeval);
114 printf("%12.12s", cp+4);
115 }
116
下面的代码没有采用缓冲机制,每次读取一条记录:
1 #include <stdio.h>
2 #include <utmp.h>
3 #include <fcntl.h>
4 #include <unistd.h>
5 #include <stdlib.h>
6 #include <time.h>
7
8 #define SHOWHOST //include remote machine on output
9
10 void show_info(struct utmp *);
11 void showtime(long timeval);
12
13 int main()
14 {
15 struct utmp current_record; //read info into here
16 int utmpfd; //read from this descriptor
17 int reclen = sizeof(current_record); //how many bytes to read
18
19 if( (utmpfd = open(UTMP_FILE, O_RDONLY)) == -1)
20 {
21 perror(UTMP_FILE); //UTMP_FILE is in utmp.h
22 exit(1);
23 }
24 /*
25 * read data structure from UTMP_FILE
26 */
27 while( read(utmpfd, ¤t_record, reclen) == reclen)
28 show_info(¤t_record);
29
30 close(utmpfd);
31
32
33 // return 0;
34 }
35
36 /*
37 * display contents of the utmp struct
38 */
39 void show_info( struct utmp * utbufp)
40 {
41 /*
42 * remove the blank record
43 * the entry ut_type in struct utmp indicate the types
44 * USER_PROCESS is the auser process
45 */
46 if(utbufp-> ut_type != USER_PROCESS) return;
47
48 printf("% -8.8s", utbufp->ut_name);
49 printf(" ");
50 printf("% -12.12s", utbufp->ut_line);
51 printf(" ");
52 //printf("%101d", utbufp->ut_time);
53 showtime(utbufp->ut_time);
54 printf(" ");
55 #ifdef SHOWHOST
56 printf("(%s)", utbufp->ut_host);
57 #endif
58 printf("\n");
59 }
60
61 void showtime(long timeval)
62 {
63 /*
64 * display time
65 */
66 char *cp;
67 cp = ctime(&timeval);
68 printf("%12.12s", cp+4);
69 }
70
可以对比一下性能,记录少的情况下不明显,但是在记录超过1000条时就可以明显看出来了。这个大家可以做一下实验。
这个who命令实现的还算比较完美。