• 用系统调用实现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);

    运行结果

  • 相关阅读:
    【目录】processing
    【目录】Qt
    【目录】python
    【目录】linux
    【目录】多线程
    【目录】Leetcode
    【leetcode】Restore IP Addresses (middle)
    linux c编程訪问数据库
    『Spring.NET+NHibernate+泛型』框架搭建之Model(二)
    hdu1316(大数的斐波那契数)
  • 原文地址:https://www.cnblogs.com/ssssspm/p/16776737.html
Copyright © 2020-2023  润新知