Linux环境编程(1) who命令

开头先介绍man命令常用用法,以后会经常使用:

注:man手册分为多个section,每个section用一个字符表示。
这里的section可以理解为类别,例如:man 1 passwd 和 man 5 passwd是不一样的类别(详细见表一)。通常我们使用man passwd,这个时候man就按照预先设置的搜索路径和顺序去搜索passwd,当搜索到一个就停止继续搜索并将结果显示出来,如果我们指定了section,那么man只会在指定的section里去查找man帮助页。
在这里插入图片描述

1.who命令能做什么

如果想知道有谁在使用linux系统,输入who命令
在这里插入图片描述

从左到右分别为:用户名、主机名、登录时间、登录的域名host

2.分析who命令的工作过程

  • 输入man who 看到描述中有一段在这里插入图片描述
  • 猜想/var/run/utmp是保存相关数据的,然后用man -k utmp
    在这里插入图片描述
  • 看到描述中有login records,再输入man 5 utmp,当中提到utmp.h,打开vim /usr/include/utmp.h
    在这dfds
  • 关键就是上面那个头文件(存放了数据结构体),以及四个等价的UTMP_FILE宏定义(代表/var/run/utmp这个路径,在path.h中有提到)
  • 再进入vim /usr/include/bits/utmp.h中查看,这一段就是我们要的
    在这里插入图片描述

ut_type:登录类型
ut_line:主机名
ut_user : 用户名(也叫#define ut_name ut_user)
ut_host:登录域名
ut_time : 登录时间 //是 ut_tv.tv_sec 定义在/usr/include/bits/time.h 即ut_time是int_32类型
在这里插入图片描述
注:
linux下存储时间常见的有两种存储方式,一个是从1970年到现在经过了多少秒(timeval),一个是用一个结构来分别存储年月日时分秒的(tm)。
在这里插入图片描述
常用时间转换函数:char *ctime(const time_t *timep);stuct tm* localtime(const time_t *timep);具体参见时间类型详解 time_t

到现在,已经大概知道who命令是怎么执行的了:就是读取文件 “/var/rum/utmp” 然后显示出来,数据通过保存结构体 utmp 来保存。现在存放登录数据的文件路径有了,对应数据结构也有了,接下来就是实践。

3.如何编写程序

思考两个问题:如何从读取文件?如何将结构体中的信息按照一定格式输出?

答:使用三个系统调用:

①打开一个文件: open
这个系统调用在进程和文件之间建立一条连接,这个连接被称为文件描述符,它就像一条由进程通向内核的管道

在这里插入图片描述在这里插入图片描述
②从文件读取数据: read
在这里插入图片描述
③关闭文件: close
在这里插入图片描述

4.开始编写程序

#include<stdio.h>
#include<utmp.h>
#include<fcntl.h>
#include<unistd.h>
#include<time.h>
#include<stdlib.h>
void show_info(utmp* Putmp)
{
	if(Putmp->ut_type!=USER_PROCESS)//去除空白登录
		return;
	printf("%-8s",Putmp->ut_name);//左对齐,若字符串长度小于8,则右补空格,大于8则完整输出
	printf(" ");
	printf("%-8s",Putmp->ut_line);//主机名
	printf(" ");
	long my_time=Putmp->ut_time;//将ut_time转为long类型
	tm* longin_time;//指向结构体tm的指针
	login_time=localtime(&my_time);
	printf("%d",login_time->tm_year+1900);//时间是从1900开始算,具体看文章开头的介绍
	printf("-");
	printf("%02d",login_time->tm_mon+1);//月份是0-11,所以要+1
	printf("-");
	printf("%02d", login_time->tm_mday);//如果不足2位,则左边补0
    printf(" ");
	printf("%02d", login_time->tm_hour);
	printf(":");
	printf("%02d", login_time->tm_min);
	printf(" ");
	printf("(%s)", Putmp->ut_host);
	printf("\n");
}
int main()
{
	utmp current_record;//保存数据的结构体
	int fd;//文件描述符
	int size=sizeof(current_record);//要读取的字节大小
	
	if((fd=open(UTMP_FILE,O_RDONLY))==-1)//如果打开出错
	{
		perror(UTMP_FILE);
		exit(1);
	}
	while(read(fd,&current_record,size)==size)//读取文件
		show_info(&current_record);//按照格式输出
	close(fd);//关闭文件
	return 0;
}

运行结果 和系统的一模一样
在这里插入图片描述

5.总结

要善用man手册,以及结合管道符和grep指令的筛选,并介绍了三个基本的系统调用:open、read、close

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值