UNIX环境高级编程022.pdf
《UNIX环境高级编程022.pdf》由会员分享,可在线阅读,更多相关《UNIX环境高级编程022.pdf(19页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、下载下载附录C 习 题 答 案第1章1.1 利用l s(1)命令中的下面两个选择项:-i显示文件或目录的i节点数目(关于i节点在4.1 4节中会详细讨论);-d如果参数是一目录,只列出其名字,而不是目录中的所有文件。执行命令的结果为:$l s-ldi/etc/./etc/.-i要求打印i节点的数量3077 drwxr-sr-x 7 bin 2048 Aug 5 20:12/etc/./2 drwxr-xr-x 13 root 512 Aug 5 20:11/etc/./$ls-ldi/./.和.的i节点数均为22 drwxr-xr-x 13 root 512 Aug 5 20:11/./2 d
2、rwxr-xr-x 13 root 512 Aug 5 20:11/./1.2 UNIX是多任务系统,所以,在程序1-4运行的同时其他两个进程也在运行。1.3 假如p e r r o r的p t r参数是一个指针,则p e r r o r就可以改变p t r所指串的内容。所以利用限定词c o n s t使得p e r r o r不能修改p t r所指的串。而s t r e r r o r的参数是错误号,由于其是整数类型并且C传递的是参数值,因此s t r e r r o r不能修改参数的值,也就没有必要使用c o n s t属性。(如果C中函数参数的处理不是很清楚,可参见K e r n i g
3、 h a n和R i t c h i e1 9 9 85.2节。)1.4 调用ff l u s h,f p r i n t f和v p r i n t f函数可修改e r r n o的值。如果它的值变了但没有保存,则最终显示的错误信息是不正确的。在过去开发的许多程序中,都可以发现不保存 e r r n o的情况,典型的错误信息是“Not at y p e w r i t e r(打字机不存在)”。5.4节中标准I/O库根据标准I/O流是否指向终端设备而改变流的缓存器。i s t t y(见11.9节)通常用来判断流是否指向终端设备,如果流不指向终端设备,e r r n o可能置为E N O T
4、 T Y,从而引起该错误。程序C-1显示了这一特性。程序C-1 errno和p r i n t f的交互作用执行上面的程序,结果为:$grep BSD/etc/motd4.3 BSD UNIX#29:Thu Mar 29 11:14:13 MST 1990$a.o u topen error:error=2 工作正常,s t d o u t是一个终端$a.out temp.foo$cat temp.fooopen error:error=25错误1.5 2038年。1.6 大约2 4 8天。第2章2.1 下面是4.3+B S D中使用的技术。在 中,用大写字母定义可在多个头文件中出现的基本数据
5、类型。例如:#i f n d e f_ A N S I _ H _#d e f i n e_ A N S I _ H _#d e f i n e_CLOCK_T_ unsigned long#d e f i n e_SIZE_T_ unsigned int.#e n d i f/*_ANSI_H_*/以下面的顺序可以在这6个头文件中分别定义s i z e _ t。#ifdef _SIZE_T_typedef _SIZE_T_ size_t;#undef _SIZE_T_#e n d i f这样,实际上只执行一次t y p e d e f。第3章3.1 所有的磁盘I/O都要经过内核的块缓存器,唯
6、一例外的是对原始磁盘设备的 I/O,但是我们不考虑这种情况(B a c h1 9 8 6的第3章讲述了这种缓存器的操作)。既然r e a d或w r i t e的数据都要被内核缓存,那么术语“无缓存装置的 I/O”指的是在用户的进程中对这两个函数不会自动缓存,每次r e a d或w r i t e就要进行一次系统调用。3.3 每次调用o p e n函数就分配一个文件表项,如果两次打开的是相同的文件,则两个文件表项指向相同的v节点。调用d u p引用已存在的文件表项(此处指 f d 1的文件表项),见图C-1。当F _ S E T F D作用于f d 1时,只影响f d 1的文件描述符标志;F
7、_ S E T F L作用于f d 1时,则影响f d 1及f d 2的文件描述符标志。3.4 如果f d是1,执行d u p 2(f d,1)后返回1,但是没有关闭描述符1(见3.1 2节)。调用3次d u p 2后,3个描述符指向相同的文件表项,所以不需要关闭描述符。如果f d是3,调用3次d u p 2后,有4个描述符指向相同的文件表项,所以需要关闭描述符3。附录C 习 题 答 案5 1 9下载图C-1 open和d u p的结果3.5 shell从左到右处理命令行,所以a.out outfile 2&1首先设置标准输出到o u t f i l e,然后执行d u p s将标准输出复制到
8、描述符2(标准错误)上,其结果是将标准输出和标准错误设置为相同的文件,即描述符 1和2指向相同的文件表项。而对于命令行a.out 2&1 outfile由于首先执行d u p s,所以描述符2成为终端(假设命令是交互执行的),标准输出重定向到o u t f i l e。结果是描述符1指向o u t f i l e的文件表项,描述符2指向终端的文件表项。3.6 这种情况之下,仍然可以用l s e e k和r e a d函数读文件中任意一处的内容。但是w r i t e函数在写数据之前会自动将文件位移量设置为文件尾,所以写文件时只能从文件尾开始,不能在任一位置。第4章4.1 stat函数总是顺一个
9、符号连接向前,所以修改后的程序不会显示文件类型是“符号连接”。例如:/b i n是/u s r/b i n的一个符号连接,但是 s t a t函数的结果只显示/b i n是一个目录,而不说明它是一个符号连接。若一个符号连接指向一不存在的文件,则 s t a t出错返回。4.2 将下面的几行语句加入#if defined(S_IFLNK)&!defined(S_ISLNK)#define S_ISLNK(mode)(mode)&S_IFMT)=S_IFLNK)#e n d i f这是一个我们编写的头文件如何屏蔽某些系统差别的实例。4.3 关闭了该文件的所有存取许可权。$umask 777$dat
10、a temp.foo$ls-l temp.foo-l stevens 29 Jan 14 06:39 temp.foo4.4 下面的命令表示关闭用户读许可权的情况。$data foo$c h m o d u-r foo关闭用户读许可权$ls-l foo验证文件的许可权-w-r w-r-l stevens29 Jul 31 09:00 foo$cat foo读文件5 2 0U N I X环境高级编程下载进程表项文件表文件状态标志当前文件位移v节点指针f d标志 p t r文件状态标志当前文件位移v节点指针v节点表v节点信息i节点信息当前文件长度cat:foo:Permission denied4
11、.5 如果用o p e n或c r e a t创建已经存在的文件,则该文件的存取许可权不变。程序 4-3可以验证这点。$rm foo bar删除文件$data foo创建文件$data bar$chmod a-r foo bar关闭所有的读许可权$ls-l foo bar验证其许可权-w-w-l stevens29 Jul 31 10:47 bar-w-w-l stevens29 Jul 31 10:47 foo$a.o u t运行程序4-3$ls-l foo bar检查文件的许可权和大小-w-w-ls t e v e n s0 Jul 31 10:47 bar-w-w-ls t e v e
12、n s0 Jul 31 10:47 foo可以看出存取许可权没有改变,但是文件长度缩短了。4.6 目录的长度从来不会是0,因为它总是包含.和.两项。符号连接的长度指其路径名包含的字符数,由于路径名中至少有一个字符,所以长度也不为 0。4.8 当创建新的c o r e文件时,内核对其存取许可权有一个默认设置,在本例中是 r w-r-r-。这一默认值可能会可能不会被 u m a s k的值修改。s h e l l对创建的重定向的新文件也有一个默认的访问许可权,本例中为r w-r w-r w-。这个值总是被当前的u m a s k修改,在本例中u m a s k为0 2。4.9 不能使用d u的原因
13、是它需要文件名,如:du tempfile或目录名,如:du.只有当u n l i n k函数返回时才释放t e m p f i l e的目录项,d u.命令没有计算仍然被t e m p f i l e占用的空间。本例中只能使用d f命令察看文件系统中实际可用的自由空间。4.10 如果被删除的链接不是该文件的最后一个链接,则该文件不会删除。此时,文件的状态改变时间被更新。如果是最后一个链接被删除,则该文件将被物理删除。这时再去更新文件的状态改变时间就没有意义,因为包含文件所有信息的i节点将会随着文件的删除而被释放。4.11 用o p e n d i r打开一个目录后,循环调用函数d o p a
14、 t h。假设o p e n d i r使用一个文件描述符,并且只有处理完目录后调用 c l o s e d i r才释放描述符,这就意味着每次打开目录就要降一级使用另外一个描述符。所以系统可打开的描述符数就限制了文件系统中树的深度。S V R 4中的f t w允许调用者指定使用的描述符数,这隐含着该实现可以关闭描述符并且重用它们。4.13 chroot函数用于辅助因特网文件传输程序(F T P)中的安全性。系统中没有帐号的用户(也称为匿名F T P)放在一个单独的目录下,利用 c h r o o t将此目录当作新的根目录就可以阻止用户访问此目录以外的文件。c h r o o t也用于在另一台
15、机器上构造一文件系统层次结构的一个副本,然后修改此副本,但不更改原来的文件系统。这可用于测试新软件包的安装。c h r o o t只能由超级用户使用,一旦更改了一个进程的r o o t,该进程及其后代进程就再也不能恢复至原先的r o o t。4.14 首先调用s t a t函数取得文件的三个时间值,然后调用 u t i m e设置期望的值。我们不希望在调用u t i m e时改变的值就是s t a t中相应的值。4.15 finger(1)对邮箱调用s t a t函数,最近一次的修改时间是上一次接收邮件的时间,最近存取时间是上一次读邮件的时间。附录C 习 题 答 案5 2 1下载4.16 对c
16、 p i o来说,既可以改变文件的访问时间(s t _ a t i m e)和修改时间(s t _ m t i m e),也可以都不改变。c p i o的-a选项可以在读文件后重新设置文件的存取时间,改变文件的存取时间。另一方面,-m将文件的修改时间和存取时间保存为归档时的值。对t a r来说,在抽取文件时,其默认方式是复原归档时的修改时间,但是-m选择项则将修改时间设置为抽取文件时的时间。无论t a r在何种情况,文件的存取时间均是抽取文件时的时间。由于不能修改状态改变时间(u t i m e也只能改变访问时间和修改时间),所以没有将其保存在文档上。4.17 read改变了文件存取时间,为了
17、消除这一影响,有些版本的 f i l e(1)调用u t i m e恢复文件的存取时间,但是这样做会修改文件的状态改变时间。4.18 内核对目录的深度没有内在的限制,但是如果路径名的长度超出了 PAT H _ M A X,则有许多命令会失败。程序 C-2创建了一个深度为 1 0 0的目录树,每一级目录名有 4 5个字符。利用g e t c w d可以得到第1 0 0级目录的绝对路径名(需要多次调用 r e a l l o c申请一个足够大的缓存)。程序C-2 创建深目录树5 2 2U N I X环境高级编程下载运行后得到:$a.o u tgetcwd failed,size=1025:Resu
18、lt too largegetcwd failed,size=1125:Result too large.3 3行getcwd failed,size=4525:Result too largelength=4613显示4 6 1 3字节的路径名但是由于文件名太长了,不能用t a r或c p i o对该目录建立档案文件,而且也不能用rm-r命令删除该目录。(怎样才能删除该目录树?)4.19 /dev目录关闭了一般用户的写许可权,所以用户不能删除目录中的文件,即 u n l i n k失败。第5章5.2 fgets函数读入数据,直到行结束或缓存满(当然会留出一个字节存放终止字符)。同样,f p
19、u t s只负责将缓存的内容输出,而并不考虑缓存中是否包含换行符。所以,如果将M A X L I N E设得很小,这两个函数仍然会正常工作,只不过被执行的次数要比 M A X L I N E值较大的时候多。如果这些函数删除或添加换行符(如g e t s和p u t s),则必需保证缓存足够大。5.3 当p r i n t f没有输出任何字符时,如:p r i n t f(),则返回0。5.4 这是一个比较常见的错误。g e t c以及g e t c h a r的返回值是整型,而不是字符型。由于E O F经常定义为1,那么如果系统使用的是有符号的字符类型,程序还可以正常工作。但如果使用的是无符号
20、字符类型,那么返回的E O F被保存到字符c后将不再是1,所以,程序会进入死循环。5.5 5个字符长的前缀、4个字符长的进程内唯一标识再加 5个字符长的系统内唯一标识(进程I D)刚好组成1 4位的U N I X传统文件长度限制。5.6 使用方法为:先调用ff l u s h后调用f s y n c,f s y n c所使用的参数由f i l e n o函数获得。如果不调用ff l u s h,所有的数据仍然在内存缓存中,此时调用f s y n c将没有任何效果。5.7 当程序交互运行时,标准输入和输出设备均为行缓存方式。每次调用 f g e t s时标准输出设备将自动刷清。第6章6.1 在S
21、 V R 4系统中,用户手册中讲述了存取阴影口令文件的函数。我们不能使用 6.2节所述函数返回的p w _ p a s s w d变量来比较加密口令。正确的方法是使用阴影口令文件中对应用户的加密口令来进行比较。在4.3+B S D系统中,口令文件的阴影是自动建立的。仅当调用者的用户I D为0时,g e t p w n a m或g e t p w u i d函数返回的p a s s e d结构中的p w _ p a s s w d字段才包含有加密口令。6.2 在S V R 4系统中,程序C-3将输出加密口令。当然,除非有超级用户许可权,否则调用g e t s p n a m将返回E A C C
22、E S错误。附录C 习 题 答 案5 2 3下载程序C-3 在S V R 4系统中输出加密口令在4.3+B S D系统中,具有超级用户许可权时,程序 C-4将输出加密口令。否则p w _ p a s s e d的返回值为星号(*)。程序C-4 在4.3+BSD系统中输出加密口令6.4 程序C-5以d a t e格式输出日期。程序C-5 以d a t e(1)的格式输出日期和时间5 2 4U N I X环境高级编程下载程序C-5的运行结果如下:$echo$TZ作者使用的默认值M S T 7$a.o u tWed Jan 15 06:48:57 MST 1992$TZ=EST5EDT a.out美
23、国东海岸Wed Jan 15 08:49:06 EST 1992$TZ=JST-9 a.out日本Wed Jan 15 22:49:12 JST 1992第7章7.1 原因在于p r i n t f的返回值(输出的字符数)变成了 m a i n函数的返回码。当然,并不是所有的系统都会出现该情况。7.2 当程序处于交互运行方式时,标准输出设备通常处于行缓存方式,所以当输出换行符时,上次的结果才被真正输出。如果标准输出设备被定向到一个文件而处于完全缓存方式,则当标准I/O清理操作执行时,结果才真正被输出。7.3 由于a g r c和a rg v不像e n v i r o n一样保存在全局变量中,所
24、以在大多数 U N I X系统中没有其他办法。7.4 当C程序复引用一个空指针出错时,执行该程序的进程将终止,于是可以利用这种方法终止进程。7.5 定义如下:typedef void Exitfunc(void);int atexit(Exitfunc*f u n c);7.6 calloc将分配的内存空间初始化为0。但是ANSI C并不保证0值与浮点0或空指针的值相同。7.7 只有通过e x e c函数执行一个程序时,才会分配堆和堆栈。7.8 可执行文件包含了用于调试c o r e文件的符号表信息,用s t r i p(1)可以删除这些信息,对两个a.o u t文件执行这条命令,它们的大小减
25、为98 304和16 384。7.9 没有使用共享库时,可执行文件的大部分都被标准I/O库所占用。7.10 这段代码不正确。因为在i f语句中定义了自动变量v a l,所以当i f中的复合语句结束时,该变量就不存在了,但是在i f语句之外又用指针引用已经不存在的自动变量v a l。第8章8.1 用下面几行代替程序8-2中调用p r i n t f的语句:i=printf(pid=%d,glob=%d,var=%dn,getpid(),glob,var);sprintf(buf,%dn,i);附录C 习 题 答 案5 2 5下载write(STDOUT_FILENO,buf,strlen(buf
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- UNIX 环境 高级 编程 022
限制150内