C语言操作utmp文件的核心函数指南:pututline、getutid与getutline

Ryan
Ryan
发布时间:2026-10-13 | 2人浏览过
原创

在Linux系统编程中,utmp.h 头文件提供了管理当前登录用户会话的关键接口。本文重点解析 pututline()、getutid() 和 getutline() 三大函数的原理、用法及注意事项,帮助开发者准确进行用户会话记录的写入与检索。

准备工作与核心机制

所有涉及 utmp 的操作均需包含 <utmp.h> 头文件。这些函数依赖于全局内部状态维护文件指针,因此在多线程环境中直接调用存在竞态风险,建议在使用前确保线程安全或通过互斥锁保护。

权限警告:修改 /var/run/utmp 或相关文件通常需要超级用户权限,普通用户执行可能因权限不足导致失败。

写入与会话更新:pututline()

pututline() 主要用于将新的用户进程信息写入 utmp 文件,或更新现有的会话记录。

第1步:构建 utmp 结构体

首先需初始化一个 struct utmp 变量,并填充关键字段。常见的字段包括:
- ut_type:记录类型,如 USER_PROCESS 表示普通用户进程。
- ut_pid:进程ID。
- ut_user:用户名。
- ut_line:终端线路,如 pts/1。
- ut_host:远程主机地址(可选)。

第2步:调用 pututline 执行写入

该函数会自动处理位置查找逻辑:若系统中已存在对应 ut_id 的记录,则更新该位置;若不存在,则追加至文件末尾。

#include <utmp.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main() {
    struct utmp ut;
    // 清零结构体是良好的编程习惯,避免随机值干扰
    memset(&ut, 0, sizeof(struct utmp));

    ut.ut_type = USER_PROCESS;
    ut.ut_pid = getpid();
    
    strncpy(ut.ut_user, "root", sizeof(ut.ut_user) - 1); // 使用 strncpy 防止溢出
    strncpy(ut.ut_line, "pts/0", sizeof(ut.ut_line) - 1);
    
    // 执行写入
    pututline(&ut);
    return 0;
}

验证方法: 编译并执行上述程序后,在终端运行 who -l 命令,应能看到刚才写入的终端条目。

基于类型的查找:getutid()

getutid() 提供灵活的查找策略,根据 ut_type 的值决定匹配规则。

第1步:确定查找模式

- 若设置 ut->ut_type 为 RUN_LVL、BOOT_TIME、NEW_TIME 或 OLD_TIME,系统将查找对应的系统级事件记录。
- 若设置 ut->ut_type 为 INIT_PROCESS、LOGIN_PROCESS、USER_PROCESS 或 DEAD_PROCESS,系统将依据 ut->ut_id 查找匹配的会话序列号。

第2步:遍历搜索结果

#include <utmp.h>
#include <stdio.h>

int main() {
    struct utmp ut, *u;
    
    // 示例:查找某个特定的用户进程记录
    ut.ut_type = USER_PROCESS;
    // 注意:ut_id 需要知道具体的会话ID才能精准定位
    // 此处演示查找 RUN_LVL (运行级别变化) 记录
    ut.ut_type = RUN_LVL;

    while ((u = getutid(&ut)) != NULL) {
        printf("Type: %d, User: %s, Line: %s\n", u->ut_type, u->ut_user, u->ut_line);
        // 注意:getutid 是单向扫描,通常无需循环直到NULL除非重置了流位置
        break; // 找到第一条匹配即可退出
    }
    return 0;
}

按终端行查找:getutline()

当需要根据物理终端(如 tty1)或伪终端(如 pts/0)查找活跃会话时,getutline() 是最直接的工具。

第1步:指定目标终端

初始化结构体时,只需填写 ut_line 字段。

第2步:持续读取直至结束

该函数会从当前文件偏移量开始,向后搜索 ut_type 为 USER_PROCESS 或 LOGIN_PROCESS 且行号匹配的记录。

#include <utmp.h>
#include <stdio.h>
#include <string.h>

int main() {
    struct utmp ut, *u;
    
    strcpy(ut.ut_line, "pts/0"); // 指定要查找的终端
    
    // 循环获取所有匹配该终端行号的进程记录
    while ((u = getutline(&ut)) != NULL) {
        printf("PID Record Found: Type=%d, User=%s\n", u->ut_type, u->ut_user);
    }
    return 0;
}

常见问题与维护建议

在进行 utmp 操作时,需注意以下事项:
1. **结构体内存清理**:始终使用 memset 清空结构体后再填充数据,未初始化的字段可能包含垃圾值导致不可预知的行为。
2. **字符串拷贝安全**:使用 strncpy 代替 strcpy,并确保目标缓冲区以空字符结尾。
3. **缓存一致性**:如果先读后写,建议调用 setutent() 重置文件指针到头部,以确保不会遗漏之前的记录或错过新追加的记录。

以上就是C语言中针对utmp文件进行查找和写入操作的详细内容,更多关于Linux系统编程及utmp.h API使用的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表