当前位置: 首页 > article >正文

Linux who命令实现:文件读写与系统编程实践

1. 从零实现Linux who命令深入理解文件读写与系统编程作为一个常年与Linux打交道的开发者我始终认为理解系统命令的实现原理是提升编程能力的最佳途径。今天我们就来解剖who这个看似简单却内涵丰富的命令通过亲手实现它来掌握Linux文件操作的核心机制。在终端输入who命令时系统会列出当前所有登录用户的信息。这背后其实是一个典型的文件读取过程 - who程序通过解析/var/run/utmp这个特殊文件来获取登录信息。下面我将带您从内核数据结构到实际代码一步步构建我们自己的who实现。2. 理解utmp文件结构2.1 utmp文件的作用与位置Linux系统通过两个关键文件记录用户登录信息/var/run/utmp记录当前登录用户会话/var/log/wtmp记录历史登录信息需要root权限访问这些文件不是普通文本文件而是由固定大小的二进制记录组成。每个登录会话对应一条记录存储在utmp结构体中。我们可以通过查看/usr/include/utmp.h头文件来了解其定义#define UT_NAMESIZE 32 #define UT_LINESIZE 32 struct utmp { short ut_type; // 记录类型 pid_t ut_pid; // 进程ID char ut_line[UT_LINESIZE]; // 终端设备名 char ut_user[UT_NAMESIZE]; // 用户名 struct timeval ut_tv; // 时间戳 // ...其他字段省略 };2.2 关键字段解析特别需要注意ut_type字段它决定了记录的类型USER_PROCESS(7)普通用户登录会话BOOT_TIME(2)系统启动记录DEAD_PROCESS(8)已终止的会话实际编程时我们发现utmp文件中包含各种类型的记录但who命令只显示USER_PROCESS类型的记录。这是第一个需要处理的细节。3. 实现文件读取逻辑3.1 文件操作三部曲Linux文件操作遵循经典的三步模式open() - 打开文件获取文件描述符read() - 循环读取数据close() - 释放资源#include fcntl.h #include unistd.h int main() { int fd open(/var/run/utmp, O_RDONLY); if(fd -1) { perror(open utmp failed); return 1; } struct utmp record; while(read(fd, record, sizeof(record)) sizeof(record)) { // 处理每条记录 } close(fd); return 0; }3.2 读取过程中的关键细节文件打开模式必须使用O_RDONLY因为utmp文件通常不允许写入read()的返回值需要严格检查它可能小于请求的字节数每次读取的字节数必须精确等于sizeof(struct utmp)否则记录会错位我在实际测试中发现如果read长度参数不正确会导致后续所有记录解析错误。这是一个典型的二进制文件处理陷阱。4. 完善信息显示功能4.1 过滤无效记录根据ut_type字段过滤掉非用户会话记录void show_info(struct utmp *ut) { if(ut-ut_type ! USER_PROCESS) return; printf(%-8s %-8s, ut-ut_user, ut-ut_line); // 显示其他信息... }4.2 时间格式转换utmp中存储的时间是从1970年1月1日开始的秒数time_t需要转换为可读格式#include time.h void show_time(time_t tv) { struct tm *tm localtime(tv); printf(%04d-%02d-%02d %02d:%02d, tm-tm_year1900, tm-tm_mon1, tm-tm_mday, tm-tm_hour, tm-tm_min); }注意tm_year是从1900年开始的年数tm_mon从0开始计数这些细节容易出错。5. 完整实现代码以下是经过优化的完整实现#include stdio.h #include utmp.h #include fcntl.h #include unistd.h #include time.h #include stdlib.h #define SHOW_HOSTNAME 1 void show_time(time_t tv) { struct tm *tm localtime(tv); printf(%04d-%02d-%02d %02d:%02d, tm-tm_year1900, tm-tm_mon1, tm-tm_mday, tm-tm_hour, tm-tm_min); } void show_info(struct utmp *ut) { if(ut-ut_type ! USER_PROCESS) return; printf(%-8s %-8s , ut-ut_user, ut-ut_line); show_time(ut-ut_tv.tv_sec); #if SHOW_HOSTNAME if(ut-ut_host[0] ! \0) printf( (%s), ut-ut_host); #endif putchar(\n); } int main() { int fd open(UTMP_FILE, O_RDONLY); if(fd -1) { perror(UTMP_FILE); exit(1); } struct utmp rec; while(read(fd, rec, sizeof(rec)) sizeof(rec)) { show_info(rec); } close(fd); return 0; }编译与测试gcc -o mywho mywho.c ./mywho6. 常见问题与调试技巧6.1 权限问题处理当程序无法打开utmp文件时检查文件路径是否正确不同Linux发行版可能不同确保程序有读取权限普通用户通常可以读取utmp6.2 结构体对齐问题如果遇到字段显示异常可能是结构体对齐问题使用#pragma pack(1)强制1字节对齐或者检查头文件版本是否匹配6.3 时间显示异常如果时间显示不正确检查时区设置/etc/localtime确保系统时间同步ntpdate命令7. 扩展思考与优化方向7.1 性能优化对于大型系统utmp文件可能包含数千条记录使用缓冲读取readv提高效率考虑只读取最新记录从文件尾部反向读取7.2 功能扩展可以增强原始who命令的功能添加登录时长统计支持按用户筛选输出彩色化显示7.3 跨平台兼容不同Unix-like系统的utmp实现略有差异使用autoconf检测系统特性为不同平台提供条件编译通过这个项目我们不仅实现了who命令的核心功能更重要的是掌握了Linux系统编程中文件操作的精髓。这种通过逆向分析系统命令来学习编程的方法可以应用到许多其他Linux命令的研究中。

相关文章:

Linux who命令实现:文件读写与系统编程实践

1. 从零实现Linux who命令:深入理解文件读写与系统编程作为一个常年与Linux打交道的开发者,我始终认为理解系统命令的实现原理是提升编程能力的最佳途径。今天我们就来解剖who这个看似简单却内涵丰富的命令,通过亲手实现它来掌握Linux文件操作…...

2026年山东省首版次高端软件申报已经开始,中承信安助力企业快速申报

对于山东省内软件和信息技术领域的企业而言,首版次高端软件申报是获取省级政策资金扶持、强化产品核心竞争力、拓宽市场发展空间的核心抓手。2026 年山东省首版次高端软件申报工作已全面启动,然而不少企业却面临政策细则把握不准、申报门槛判断不清、申报…...

依赖p4est库的程序windows运行方法----支持vs2022调试

一.前置环境 1.vs2022且包含CLangCL工具集,没有安的在vs的intaller里边修改已安装的vs2022,在右侧目录里勾选上(使用c进行桌面开发/适用于windows的CClang工具)。 2.安装MS-MPI,安在默认位置即可(https://www.micros…...

群晖 /dev/md0 根分区爆满 100% 排查清理全流程

解决群辉系统爆满安装不了套件 一、群辉安装套件报错 报错:系统分区的可用空间不足,请联络Synology支持小组来寻求帮助。这是因为系统分区(System Partition)空间不足,导致无法解压和安装该套件。与磁盘硬盘大小没有关…...

2026年,行业内热门GEO搜索优化公司口碑究竟如何?

你是否在为提升品牌在搜索引擎上的排名而烦恼?是否因高昂的优化成本和复杂的操作望而却步?又或者担心优化效果不佳,无法实现询盘转化?今天,我们就来深入探讨一下2026年热门的GEO优化软件,看看哪款能真正解决…...

OpenClaw多模型切换实战:千问3.5-35B-A3B-FP8与文本模型的协作流程

OpenClaw多模型切换实战:千问3.5-35B-A3B-FP8与文本模型的协作流程 1. 为什么需要多模型协作? 去年我在尝试用AI自动化处理工作流时,发现一个尴尬的问题:当我用同一个模型处理图片识别和文本写作时,要么图片理解能力…...

Go Channel 缓冲区机制分析

Go Channel 缓冲区机制分析 在Go语言的并发编程中,Channel是协程间通信的核心机制之一。其缓冲区机制的设计直接影响程序的性能和稳定性。理解缓冲区的运作原理,能够帮助开发者更高效地利用Channel,避免死锁或资源浪费。本文将从缓冲区的本质…...

嵌入式ONPS协议栈:轻量级TCP/IP实现与优化

1. ONPS协议栈概述ONPS是一款专为资源受限的嵌入式系统设计的开源网络协议栈,由国内开发者完全自主开发实现。作为一名长期从事嵌入式网络开发的工程师,我第一次接触ONPS时就对其轻量级设计和完整的功能实现印象深刻。与常见的LwIP等协议栈相比&#xff…...

OpenClaw隐私保护方案:Qwen3-14B本地处理敏感数据

OpenClaw隐私保护方案:Qwen3-14B本地处理敏感数据 1. 为什么需要本地化隐私保护方案 去年我在处理一批医疗研究数据时,曾因使用某云端AI服务导致文件误传至公共存储桶。虽然及时删除了数据,但这次经历让我意识到:当涉及法律文书…...

Ostrakon-VL-8B对比评测:主流开源多模态模型在餐饮场景的较量

Ostrakon-VL-8B对比评测:主流开源多模态模型在餐饮场景的较量 最近在餐饮和零售行业,用AI来“看懂”图片的需求越来越多了。比如,自动识别菜品、分析菜单、甚至根据顾客拍的模糊照片推荐相似菜品。这背后,多模态模型是关键。 市…...

数据处理与统计分析----沙箱

命令行操作沙箱...

终极指南:免费解锁Cursor Pro完整功能,告别AI编程限制

终极指南:免费解锁Cursor Pro完整功能,告别AI编程限制 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reach…...

C++的std--filesystem文件系统库与跨平台路径处理的标准化

C的std::filesystem文件系统库与跨平台路径处理的标准化 在现代软件开发中,跨平台文件系统操作一直是一个复杂且容易出错的挑战。不同操作系统(如Windows、Linux和macOS)使用不同的路径分隔符和文件系统语义,开发者往往需要编写大…...

AI 模型调度平台的系统架构

AI模型调度平台的系统架构:智能时代的核心引擎 在人工智能技术飞速发展的今天,AI模型调度平台成为企业实现智能化转型的关键基础设施。它通过高效管理、调度和优化AI模型资源,帮助用户快速部署和运行复杂的AI任务。本文将深入解析AI模型调度…...

C++ 模板元编程在性能优化中的作用

C 模板元编程在性能优化中的作用 在现代C开发中,性能优化始终是开发者关注的核心问题之一。而模板元编程(Template Metaprogramming, TMP)作为一种编译期计算技术,能够在程序运行前完成复杂的逻辑处理,从而显著提升运…...

Go Routine 调度与系统线程绑定

Go语言凭借其轻量级并发模型Goroutine,成为高并发场景下的明星语言。Goroutine的魔力源于其高效的调度机制,而它与系统线程的绑定关系更是性能优化的关键。本文将揭开Goroutine调度与线程绑定的技术面纱,从运行时调度器、线程池管理、工作窃取…...

嵌入式LED闪烁控制库Blinker工程实践指南

1. Blinker:嵌入式LED闪烁控制库的工程化实现解析Blinker并非一个广为人知的通用开源库,其项目摘要“Simple library for LED blinking”与关键词“blinking, led”表明这是一个高度聚焦、轻量级的底层驱动组件。在嵌入式系统开发中,“LED闪烁…...

AI 模型推理中的延迟分析与测试

AI 模型推理中的延迟分析与测试 在人工智能技术快速发展的今天,AI 模型的推理性能成为影响实际应用效果的关键因素之一。无论是智能语音助手、自动驾驶,还是实时推荐系统,延迟的高低直接决定了用户体验的好坏。对 AI 模型推理的延迟进行分析…...

M24LR64E-R双接口NFC标签驱动与嵌入式集成指南

1. 项目概述NFC Tag M24LR6E 是一款面向嵌入式系统的 Arduino 兼容库,专为驱动 Seeed Studio 推出的 Grove - NFC Tag 模块而设计。该模块核心芯片为 STMicroelectronics 的 M24LR64E-R,是一款高度集成的双接口(IC RF)近场通信标…...

Ubuntu20.04部署RTKLIB-QT:从源码编译到GUI应用实战

1. 为什么要在Ubuntu上部署RTKLIB-QT? 如果你正在处理GNSS(全球导航卫星系统)数据,比如GPS、GLONASS或北斗的观测数据,RTKLIB绝对是你工具箱里不可或缺的利器。这个开源软件包在Windows下有成熟的GUI版本,但…...

Docker快速部署Nacos

生成数据目录sudo mkdir -p /app/nacos/logs sudo mkdir -p /app/nacos/data sudo chmod -R 777 /app/nacos生成一个随的 Base64 密钥:openssl rand -base64 32nacos启动命令docker run --name nacos-server \-e MODEstandalone \-v /app/nacos/logs:/home/nacos/lo…...

电路板测试点设计与自动化测试实践

1. 测试点的本质作用在电子制造领域,测试点(Test Point)是电路板上那些看似多余的小圆点,但它们却是保证产品质量的关键设计。作为一名有十年经验的硬件工程师,我见过太多因为忽视测试点设计而导致量产失败的案例。测试…...

功率半导体技术:GaN与SiC的性能对比与应用指南

1. 功率半导体技术演进背景在电力电子领域,功率半导体器件的发展经历了从硅(Si)到第三代半导体材料的重大跨越。作为工程师,我们正站在技术革新的关键节点:氮化镓(GaN)和碳化硅(SiC)这两种宽禁带半导体材料正在重塑功率转换的格局。传统硅基功…...

哈佛医学院做了5679次组学分析:大模型能力没差别,关键在验证

哈佛医学院Zitnik团队的MEDEA 给出了一条明确的技术路线:与其追求更强的骨干大模型,不如在分析流程的每一步嵌入验证机制。在理解 MEDEA 的设计逻辑之前,先看一组来自消融实验的数据。在细胞类型特异性靶点发现任务中,研究团队将M…...

轻量级抢占式任务调度器:面向Arduino的毫秒级实时调度

1. 项目概述Task Scheduler是一款专为 Atmel AVR(ATmega328P/ATmega2560)与 ARM Cortex-M3(SAM3X8E)架构微控制器设计的轻量级、抢占式实时任务调度器,面向 Arduino 生态系统深度优化。其核心目标并非替代完整 RTOS&am…...

Claude Code开源第一人,竟是华人辍学博士!CC之父回应:纯手误

51万行Claude Code代码全网裸奔,背后泄密第一人竟是他。就在刚刚,CC之父回应来了:是人,不是Bun。爆出Claude Code源码第一人,竟被全网扒出来了!3月31日凌晨4点23分,安全研究员Chaofan Shou在X上…...

遥感影像解译实战:从目视解译八要素到精准分类

1. 遥感影像解译的底层逻辑 第一次接触遥感影像时,我盯着屏幕上的彩色方块发懵——这堆像素点怎么能看出是森林还是农田?后来才发现,解译就像玩"大家来找茬",关键要掌握八要素这把万能钥匙。大小、形状、阴影、颜色、纹…...

Arduino驱动OV7670图像传感器:底层时序与跨平台实现

1. Arduino_OV767X 库深度解析:OV7670 CMOS 图像传感器在 Arduino 平台上的底层驱动与工程实践OV7670 是 OmniVision(现属韦尔半导体)于 2000 年代初推出的超低功耗、单芯片 QVGA(320240)彩色 CMOS 图像传感器。其采用…...

[特殊字符] iONSPlayer 发布,ONScripter游戏的iOS模拟器

🎮 iONSPlayer 发布,ONScripter游戏的iOS模拟器 阿丰在长春 一只特立独行的丰子 什么是 iONSPlayer?继承自ONSPlayer! iONSPlayer 是一款运行在 iOS 设备上的 ONScripter 引擎模拟器。 简单来说,它可以让你在 iPhon…...

Arduino嵌入式轻量日志库SimpleLogger设计与实践

1. 项目概述SimpleLogger 是一款专为 Arduino 平台设计的轻量级日志库,其核心设计哲学是“极简可用、零侵入、低资源占用”。在资源受限的微控制器(如 ATmega328P、ESP32-S2、nRF52840 等)上,传统日志框架(如 ArduinoL…...