• 用系统调用实现who命令mywho


    who功能

    man who来查看who命令的功能:

    who命令用于显示系统中有哪些使用者正在上面,显示的资料包含了使用者 ID、使用的终端机、从哪边连上来的、上线时间、呆滞时间、CPU 使用量、动作等等。

    相关参数
    -H 或 --heading:显示各栏位的标题信息列;
    -i 或 -u 或 --idle:显示闲置时间,若该用户在前一分钟之内有进行任何动作,将标示成"."号,如果该用户已超过24小时没有任何动作,则标示出"old"字符串;
    -m:此参数的效果和指定"am i"字符串相同;
    -q 或--count:只显示登入系统的帐号名称和总人数;
    -s:此参数将忽略不予处理,仅负责解决who指令其他版本的兼容性问题;
    -w 或-T或--mesg或--message或--writable:显示用户的信息状态栏;
    --help:在线帮助;
    --version:显示版本信息。
    
    who功能原理

    who的原理便是读取/var/run/utmp部分文件内容,输出到屏幕。所以我们考虑使用系统调用,调用utmp函数,来实现显示使用者系统的信息。

    utmp

    输入man utmp,查看utmp的具体功能:

    还可以看到utmp结构体的结构:

    可以发现utmp可以显示登陆者的pid、登陆设备、登陆者的名字、登录主机的名字、退出状态等等,其中,登录时间被保存在tu_tv中。
    利用utmp系统调用(#include<utmp.h>),编写mywho代码,实现与who命令一样的功能:

    代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <utmp.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <time.h>
    #define SHOWOST
    void showinfo(struct utmp *utbufp);
    long showtime(long timeval);
    int main()
    {
            struct utmp current_record;
            int utmpfd;
            int reclen = sizeof(current_record);
            if((utmpfd = open(UTMP_FILE,O_RDONLY))==-1)
            {
                    perror(UTMP_FILE);
                    exit(1);
            }
            while (read(utmpfd,&current_record,reclen)==reclen)
                    showinfo(&current_record);
            close(utmpfd);
            return 0;
    }
    void showinfo(struct utmp *utbufp){
            if(utbufp->ut_type!=USER_PROCESS)
                    return;
            else{
                    printf("%-8.8s",utbufp->ut_name);
                    printf(" ");
                    printf("%-8.8s",utbufp->ut_line);
                    printf(" ");
                    showtime(utbufp->ut_time);
                    printf(" ");
                    printf("(%s)",utbufp->ut_host);
                    printf(" ");
            }
    }
    long showtime(long timeval)
    {
            struct tm *cp;
            cp = gmtime(&timeval);
            printf("    ");
            printf("%d-%d-%d %d:%d ",cp->tm_year+1900,cp->tm_mon+1,cp->tm_mday,(cp->tm_hour+8)%24,cp->tm_min);
    }
    
    • main函数使用系统调用open,read,close对utmp文件进行操作。
    • 使用showtime()函数,调用tm结构体完成对时间的输出
      tm结构体的内容如下:
    struct tm 
    {  
    int tm_sec;		 /* 秒–取值区间为[0,59] */   
    int tm_min; 		 /* 分 - 取值区间为[0,59] */   
    int tm_hour; 	         /* 时 - 取值区间为[0,23] */   
    int tm_mday;		 /* 一个月中的日期 - 取值区间为[1,31] */  
    int tm_mon;		 /* 月份(从一月开始,0代表一月) - 取值区间为[0,11] */ 
    int tm_year; 	         /* 年份,其值从1900开始 */  
    int tm_wday; 	         /* 星期–取值区间为[0,6],其中0代表星期天,1代表星期一,以此类推 */  
    int tm_yday; 	         /* 从每年的1月1日开始的天数–取值区间为[0,365],其中0代表1月1日,1代表1月2日,以此类推 */  
    int tm_isdst; 	         /* 夏令时标识符,实行夏令时的时候,tm_isdst为正。不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负。*/  
    long int tm_gmtoff;	 /*指定了日期变更线东面时区中UTC东部时区正秒数或UTC西部时区的负秒数*/   
    const char *tm_zone;     /*当前时区的名字(与环境变量TZ有关)*/  
    }; 
    

    tm结构体是在Linux编程中较为常用的结构体,通过观察tm结构体的类型可以看出调用tm可以输出年月日、时分秒等,

    • utbufp->ut_time是一个时间数据,其储存的是从1970年1月1日0:00开始到现在所经过的秒数。

    • C 库函数 struct tm *gmtime(const time_t *timer) 使用 timer 的值来填充 tm 结构,并用协调世界时(UTC)也被称为格林尼治标准时间(GMT)表示。用cp = gmtime(&timeval);来获取当前时间,通过gmtime可以将这个数据转换为结构体tm。

    • 需要注意的是tm结构体中tm_year年份数值是减去了1900年,所以输出时需要加上1900。

    printf("%d-%d-%d %d:%d ",cp->tm_year+1900,cp->tm_mon+1,cp->tm_mday,(cp->tm_hour+8)%24,cp->tm_min);

    运行结果

  • 相关阅读:
    LC.225. Implement Stack using Queues(using two queues)
    LC.232. Implement Queue using Stacks(use two stacks)
    sort numbers with two stacks(many duplicates)
    LC.154. Find Minimum in Rotated Sorted Array II
    LC.81. Search in Rotated Sorted Array II
    LC.35.Search Insert Position
    前后端分离:(一)
    Redis基本使用(一)
    GIT篇章(二)
    GIT篇章(一)
  • 原文地址:https://www.cnblogs.com/ssssspm/p/16776737.html
Copyright © 2020-2023  润新知