《Unix-Linux编程实践教程》读书笔记(二)

本文详细解析Unix系统中的who命令实现原理及其文件操作过程,包括如何读取utmp文件来获取用户登录信息,并介绍文件操作相关系统调用如open、read、close等。

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

 

第二章  用户、文件操作与联机帮助:编写who命令

1.      本章分析who命令,进一步学习文件操作(在第一章中已经初步使用文件操作相关函数)。除此之外,还将学习从Unix的联机帮助中得到有用信息。


2.      Unix系统的标准命令存放路径:/bin,/usr/bin, /usr/local/bin .当在终端使用某个标准命令时,系统会从以上路径搜索。将自己写好的可执行程序放进上述目录就能在终端调用。


3.      命令who的使用、命令输出的含义。


4.      联机帮助命令man,DESCRIPTION、OPTIONS、SEE ALSO部分。搜索联机帮助:

#man  -k  XXX      //XXX是要搜索的关键字

#man  num instruction //指定查阅命令instruction的第num节联机帮助文档


5.      Unix系统中的大多数头文件存放路径:/usr/include


6.      通过上述4、5中关于联机帮助使用的学习,查找到命令who所读取的文件utmp.h文件,且who的原理就是读取该文件中的信息,信息由用户登陆的标准结构体组成,该结构体分析头文件可知。


7.      编程涉及到的文件读写的系统调用:open、read、close

1) open函数的语法,文件描述符是进程和文件之间的一条链接,是进程进入内核的通道,而文件具体操作交由内核完成。

2) Unix允许多个进程打开同一个文件,即同时访问同一个文件。同一个进程可以打开多个文件,一个文件也可以被多个进程打开,但是不管哪种情况,每次open函数返回的文件描述符不一样。

3)  read函数的语法。

4)  close函数的语法,该函数关闭进程和文件之间的链接。


8.      perror()的使用,当某个调用出错时,系统自动将错误代码存储在errno中,调用perror()会根据errno打印对应的出错信息。


9.      who_1.c和who_2.c的实现,其中who_2.c完善了对当前登录用户的过滤(方法是查看当前读取的用户登录信息结构体的ut_type成员变量,该变量指明了是否为当前登录或者其他类型),以及long int时间转化为可读字符串的方法(使用ctime(),Unix时间的处理方式)。


10.  cp命令的基本用法,其涉及的其他系统调用:create()、write()。


11.  更深层次的思考:应用缓冲和内核缓冲。系统调用次数较多时(譬如每次read较少信息,read次数就会较多)花费的时间开销较大是因为系统上下文运行环境的切换需要时间。


12.  who_2.c在应用缓冲上的改进,每次读取16个utmp结构体信息存在buffer中,每次取一个,直到buffer为空时才进行下一次从内核复制16个utmp结构体信息的动作,而内核中的信息同样来自于内核中缓冲技术的使用。


13.  文件的读写:像utmp文件这样包含规整结构体信息的文件,可以在退出登录的时候对其进行查找和修改,以说明用户的登录状态。实现退出登录的上述修改,除了使用上述系统调用之外,还需要用到lseek()函数。该函数能够定位文件读写位置。


14.  小结

1)  who命令, w命令

2)  文件操作系统调用:

open(), create(), close(), read(), write(), lseek()

3)  文件描述符可以看作是程序和文件之间的链接

4)  应用程序通过缓冲机制减少调用系统调用的次数,内核通过系统调用减少降低内核进行磁盘i/o操作的次数,从而提高应用程序和内核的工作效率。

5)  errorn和perror()的使用

6)  在第一章和第二章中都是用了和文件相关的操作,究竟有何区别,选择哪一类呢?标准C函数:fopen(), getc(), gclose(), gfets() 都实现了用户级的缓冲(也就是说应用程序调用fread会有缓冲效果,其本身是对read的封装,应用的每次fread调用可能不会每次都发起read调用),使用FILE结构。


*********************************************************************************************************************************************************************

关于 read/write 同 fread/fwrite 的 区别:

这篇文章有点问题(基本上是会引起读者误解的)
/* ********************************************************************************************* */
fread是带缓冲的,read不带缓冲,举个例子:
如果文件的大小是8k。
你如果用read/write,且只分配了2k的缓存,则要将此文件读出需要做4次系统调用来实际从磁盘上读出。
如果你用fread/fwrite,则系统自动分配缓存,则读出此文件只要一次系统调用从磁盘上读出。
也就是用read/write要读4次磁盘,而用fread/fwrite则只要读1次磁盘。效率比read/write要高4倍。
如果程序对内存有限制,则用read/write比较好。
/* ********************************************************************************************* */

>> fread是带缓冲的,read不带缓冲
<< fread带缓冲,是指在应用层带缓冲。
<< read也是带了缓存的,在用户看不到的系统层, 当然,也可以是不带缓冲,直接DMA,这个要看OS的实现者的心情了。

>> 你如果用read/write,且只分配了2k的缓存,则要将此文件读出需要做4次系统调用来实际从磁盘上读出。
<< 我想,他想说的是每次读2K,缓存当然是你分配的,问题是:为什么你只给它分配2K?

:::::::::::::::::::::::::::::::::::::::
其实fread和read的区别是,fread并不一定每次者会调用read。
fread在应用层实现了缓存。所以
你做以下操作:
1. 打开文件
2. 读文件 0~4K  (Fread或Read)
3. 其它操作
4. 读文件 1~3K  (Fread或Read)
5. 关文件

如果你用read ,则步骤4要调用内核
但如果你用的fread,则因为步骤2,缓存中已有所需内容,直接可以返回给你,不用再次调用内核

两者各有好处,这种情况下fread被认为比较高效
但READ能够实时反映文件的内容,如果该文件可能被其它进程更改的话

此外需要说明的是,fread/fwrite 的可移植性好于 read/write;但 fread/fwrite 作为 read/write 的封装,某些情况下效率可能并不会优于后者。

*********************************************************************************************************************************************************************

----------------------------------------------------------------------------------------

本文链接http://blog.youkuaiyun.com/yongchurui/article/details/22334641

2014.03.27


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值