您的位置:首页 > 运维架构 > Linux

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

2014-03-27 23:25 225 查看
 

第二章  用户、文件操作与联机帮助:编写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.csdn.net/yongchurui/article/details/22334641

2014.03.27

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息