《unix/linux编程实践教程》学习笔记:第二章 编写who,cp命令

本文介绍了如何从零开始实现一个简单的who命令。通过解析utmp文件并利用C语言标准库函数,实现了显示当前登录用户的功能。文章还详细解释了文件描述符、缓冲区等概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本人使用的操作系统是:Ubuntu 16
编写之前的准备:
学习编写who命令的第一步在于学会了解who命令的相关信息。
我们使用联机帮助命令man,来参看man的帮助。

man who

我们可以在描述中看到相关信息:

   If FILE is not specified, use /var/run/utmp.  /var/log/wtmp as FILE  is common.   If  ARG1  ARG2  given, -m presumed: 'am i' or 'mom likes' are usual.

继续使用

man -k utmp

可以看到

utmp (5)             - login records

于是继续参看

man 5 utmp
NAME
       utmp, wtmp - login records

SYNOPSIS
       #include <utmp.h>

到此我们就可以知道who命令的工作原理:
我们通过读取utmp文件里的信息来实现查看登录用户的功能,同时utmp是以结构体的形式储存用户信息。

编写who命令
1.如何从文件中读取数据结构
我们可以通过

man -k file | grep read 

来查找相关信息。
解决方法是通过unix的文件操作函数:
open,read,write,lseek,close

2.时间格式转换
unix系统中,时间是用一个整数来表示,他是从1970年1月1日0时开始所经历的的秒数,在头文件time.h中可以查看:

typedef long int time_t;

可以通过ctime函数将 time_t 转化为常见的时间格式。

代码:
http://blog.youkuaiyun.com/yz764127031/article/details/53066618

编写cp

void oops(char *,char *);

int main(int ac,char *av[])
{
    int in_fd,out_fd,n_chars;
    char buf[BUFFERSIZE];

    if(ac != 3){
    fprintf(stderr,"usage:%s sourse destination\n",* av);
    exit(1);
    }

    if((in_fd = open(av[1],O_RDONLY)) == -1)
        oops("Cannot open",av[1]);

    if((out_fd = creat(av[2],0644)) == -1)
        oops("Cannot open",av[2]);

    while((n_chars = read(in_fd,buf,BUFFERSIZE))>0)
        if(write(out_fd,buf,n_chars) != n_chars)
                oops("Write error to ",av[2]);

    if(n_chars == -1 ){
        printf("iii");
        oops("Read error from",av[1]);
    }
    if(close(in_fd)==-1||close(out_fd)==-1)
        oops("Error closing files","");
}



void oops(char *s1,char *s2)
{
    fprintf(stderr,"Error: %s",s1);
    perror(s2);
    exit(1);
}

小结:
1.引入了文件描述符的概念:
当用户第一次请求对某文件进行操作时,须县利用open系统调用将文件打开,所谓打开就是指系统将指定文件的属性,从外存拷贝到内存,打开文件表的一个表目中,并将该表目的编号(或称为索引号)返回给用户。这个编号就是文件描述符,通过内核返回,文件描述符在文件和进程之间建立了一条连接,它像一条由进程通向内核的管道。
之后的read,write,lseek,close都是建立在使用文件描述符的基础上。

2.
open文件的同时需要指定他的操作权限:
O_RDONLY,O_WRONLY,O_RDWR
分为只读,只写,和读写三种,违反权限的操作将会报错

3.引入缓冲区的概念:
使用缓冲区可以有效提高文件IO操作的效率。
主要思想:一次读入大量的数据放入缓冲区,需要的时候从缓冲区取得数据。
我们通过建立缓冲区,可以有效的减少系统调用的次数。
原因:使用系统调用开销较大,因为用户进程位于用户空间,内核位于系统空间,磁盘只能被内核直接访问,程序要读取磁盘上的数据需要通过系统调用read,而read的代码在内核中,所以当read调用发生时,执行权会从用户代码转移到内核代码,执行内核代码是需要时间的。
当运行内核代码时,CPU工作在管态,需要对应一些特殊的堆栈和内存环境,必须在系统调用时建立好,系统调用结束后,CPU又要切换到用户模式,必须把堆栈和内存环境恢复为用户程序运行时的状态,这种运行环境的切换需要消耗很多时间。

内核缓冲技术:
当进程需要的数据不在内核缓冲区时,内核把相应的数据块加入到请求数据列表中,然后将该进程挂起,接着为其他进程服务。
一段时间后,内核把相应的数据块从磁盘读入内核缓冲区,然后在把数据复制到进程缓冲区中,最后唤醒被挂起的进程。

4.文件指针
unix每次打开一个文件都会保存一个指针来记录文件的当前位置,当从文件读数据时,内核从指针所表明的地方,读取指定的直接,然后移动位置指针,指向下一个未被读取的字节,写文件的操作也是类似的。
指针与文件描述符相关联,而不是与文件关联,所以如果两个程序同时打开一个文件,这时会有两个指针,两个程序对文件的读操作不会互相干扰。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值