⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 appendix_c.htm

📁 UNIX环境下C编程的详细详细介绍
💻 HTM
📖 第 1 页 / 共 4 页
字号:
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 3.0">
<title>C:\WINDOWS\Desktop\UnixProg\7.htm</title>
</head>

<body>
<font SIZE="2">

<h1 align="center">附录C 习题答案 </h1>

<p>第一章 </p>

<p>1.1 利用ls命令中的下面两个选项:-i--显示文件或目录的i节点数目(关于</p>

<p>i节点 </p>

<p>在4.14节中会详细讨论);-d--如果参数是一目录,只列出其名字,而不是</p>

<p>目录中 </p>

<p>的所有文件。 </p>

<p>执行下面命令的结果为: </p>

<p>$ ls -ldi /etc/. /etc/.. </p>

<p>3077 drwxr-sr-x 7 bin 2048 Aug 5 20:12 /etc/./ </p>

<p>2 drwxr-xr-x 13 root 512 Aug 5 20:11 /etc/../ </p>

<p>$ls -ldi /. /.. </p>

<p>2 drwxr-xr-x 13 root 512 Aug 5 20:11 /./ </p>

<p>2 srwxr-xr-x 13 root 512 Aug 5 20:11 /../ {.和..的的i节点数均</p>

<p>为2 </p>

<p>的i节点数均为2 </p>

<p>1.3 假如perror的ptr参数是一个指针,则perror就可以改变ptr所指串的</p>

<p>内容。所 </p>

<p>以利用限定词const使得perror不能修改ptr所指的串。而strerror的参数</p>

<p>是错误号 </p>

<p>,由于其是整数类型并且C传递的是参数值,因此strerror不能修改参数的</p>

<p>值,也 </p>

<p> </p>

<p>就没有必要使用const属性。 </p>

<p>1.4 调用fflush,fprintf和vprintf函数会改变errno的值。如果它的值</p>

<p>变了但没 </p>

<p>有保存,则最终显示的错误信息是不正确的。 </p>

<p>在过去开发许多程序中都可以发现不保存errno的情况,典型的打印出的错误</p>

<p>信息 </p>

<p>是&quot;Not a typewriter.&quot;。在5.4节中标准I/O库根据标准I/O流是否指向终</p>

<p>端设备而 </p>

<p>改变流的缓存器。istty(11.9节)通常用来判断流是否指向终端设备,如果</p>

<p>流不指 </p>

<p>向终端设备,errno可能置为ENOTTY,从而引起该错误。程序C.1表现了这个</p>

<p>属性。 </p>

<p>#include &lt;stdio.h&gt; </p>

<p>/* </p>

<p>* The following prints errno=25 (ENOTTY) under 4.3BSD and</p>

<p>SVR2, </p>

<p>* when stdout is redirected to a file. </p>

<p>* Under SVR4 and 44BSD it works OK. </p>

<p>*/ </p>

<p>int </p>

<p>main() </p>

<p>{ </p>

<p>int fd; </p>

<p>extern int errno; </p>

<p>if ( (fd = open(&quot;/no/such/file&quot;, 0)) &lt; 0) { </p>

<p>printf(&quot;open error: &quot;); </p>

<p>printf(&quot;errno = %d\n&quot;, errno); </p>

<p>} </p>

<p>exit(0); </p>

<p>} </p>

<p>程序 C.1 errno和printf的交互作用 </p>

<p>执行上面的程序,结果为: </p>

<p>$ grep BSD /etc/motd </p>

<p>4.3 BSD UNIX #29: Thu Mar 29 11:14:13 MST 1990 </p>

<p>$ a.out </p>

<p>open error: error = 2 {工作正常,stdout是一个终端} </p>

<p>$ a.out &gt; temp.foo </p>

<p>$ cat temp.foo </p>

<p>open error: error = 25 {错误} </p>

<p>1.5 2038年。 </p>

<p>1.6 大约248天。 </p>

<p> </p>

<p>第二章 </p>

<p>2.1 下面是4.3+BSD中使用的技术。在&lt;machine/ansi.h&gt; 
中,用大写字母</p>

<p>定义可以 </p>

<p>在多个头文件中出现的基本数据类型。例如: </p>

<p>#ifndef _ANSI_--H_ </p>

<p>#define _ANSI_H_ </p>

<p>#define _CLOCK_T_ unsigned long </p>

<p>#define _SIZE_T_ unsigned int </p>

<p>… </p>

<p>#endif /*_ANSI_H_*/ </p>

<p>以下面的顺序可以在这6个头文件中分别定义size_t。 </p>

<p>#ifdef _SIZE_T_ </p>

<p>typedef _SIZE_T_ size_t; </p>

<p>#undef _SIZE_T_ </p>

<p>#endif </p>

<p>这样,实际上只执行一次typedef。 </p>

<p> </p>

<p>第三章 </p>

<p>3.1 所有的磁盘I/O都要经过内核的块缓存器,唯一例外的是对原始磁盘设备</p>

<p>的I/ </p>

<p>O,但是我们不考虑这种情况(Bach [1986] 
中的第三章讲述了这种缓存器的</p>

<p>操作) </p>

<p>。既然read或write的数据都要被内核缓存,那么术语&quot;无缓存装置的I/O&quot;指</p>

<p>的是在 </p>

<p>用户的进程中对这两个函数不会自动缓存,每次read或write就要进行一次</p>

<p>系统调 </p>

<p>用。 </p>

<p>3.3 每次调用open函数就分配一个文件表项,如果两次打开的是相同的文</p>

<p>件,则两 </p>

<p>个文件表项指向相同的v节点。调用dup引用已存在的文件表项(此处指fd1的</p>

<p>文件表 </p>

<p>项),见图C.1。当F_SETFD作用于fd1时,只影响fd1的文件描述符标志;</p>

<p>F_SETFL作 </p>

<p>用于fd1时,则影响fd1及fd2的文件描述符标志。 </p>

<p>图C.1 open和dup的结果 </p>

<p>3.4 如果fd是1,执行dup2(fd,1)后返回1,但是没有关闭描述符1(参见</p>

<p>3.12节)。 </p>

<p>调用3次dup2后,3个描述符指向相同的文件表项,所以不需要关闭描述符。 
</p>

<p>如果fd是3,调用3次dup2后,有4个描述符指向相同的文件表项,所以就需</p>

<p>要关闭 </p>

<p>描述符3。 </p>

<p>3.5 shell是从左到右处理命令行,所以 </p>

<p>a.out &gt; outfile 2 &gt;&amp;1 </p>

<p>首先设置标准输出到outfile,然后执行dups将标准输出复制到描述符2(标</p>

<p>准错误 </p>

<p>)上,其结果是将标准输出和标准错误设置为相同的文件,即描述符1和2指向</p>

<p>相同 </p>

<p>的文件表项。 </p>

<p>而对于命令行 </p>

<p>a.out 2 &gt; &amp;1 &gt;outfile </p>

<p>由于首先执行dups,所以描述符2成为终端(假设命令是交互执行的),标准输</p>

<p>出重 </p>

<p>定向到outfile。结果是描述符1指向outfile的文件表项,描述符2指向终端</p>

<p>的文件 </p>

<p>表项。 </p>

<p>3.6 这种情况之下,仍然可以用lseek和read函数读文件中任何一处的内</p>

<p>容。但是 </p>

<p>write函数在写数据之前会自动将文件偏移量设置为文件尾,所以写文件时只</p>

<p>能从 </p>

<p>文件尾开始,不能在任意位置。 </p>

<p> </p>

<p>第四章 </p>

<p>4.1 stat函数总是顺一个符号连接向前,所以修改后的程序不会显示文件类</p>

<p>型是&quot; </p>

<p>符号连接&quot;。例如:/bin是/usr/bin的一个符号连接,但是stat函数的结果</p>

<p>只显示 </p>

<p>/bin是一个目录,而不说明它是一个符号连接。若一个符号连接指向一不存</p>

<p>在的文 </p>

<p>件,则stat出错返回。 </p>

<p>4.2 将下面的几行语句加入&lt;ourhdr.h&gt; </p>

<p>#if defined ( S_IFLNK ) &amp;&amp; !defined ( S_ISLNK ) </p>

<p>#define S_ISLNK ( mode ) ((( mode ) &amp; S_IFMT ) == S_IFLNK ) </p>

<p>#endif </p>

<p>这是一个我们编写的头文件如何屏蔽某些系统差别的实例。 </p>

<p>4.3 关闭了该文件的所有存取权限。 </p>

<p>$ umask 777 </p>

<p>$ data &gt; temp.foo </p>

<p>$ ls -l temp.foo </p>

<p>---------- l stevens 29 Jan 14 </p>

<p>6:39 temp.foo </p>

<p>4.4 下面的命令表示关闭用户读权限的情况。 </p>

<p>$ data &gt; foo </p>

<p>$ chmod u-r foo {关闭用? </p>

<p>读权限} </p>

<p>$ ls -l foo </p>

<p>验证文件的权限} </p>

<p>--w-rw-r-- l stevens 29 Jul 31 09:00 </p>

<p>oo </p>

<p>$ cat foo </p>

<p>{读文件} </p>

<p>cat: foo: Permission denied </p>

<p>4.5 如果用open或creat创建已经存在的文件,则该文件的存取权限不变。</p>

<p>通过程 </p>

<p>序4.3可以验证这点。 </p>

<p>$ rm foo bar </p>

<p>删除文件} </p>

<p>$ data &gt; foo </p>

<p>创建文件} </p>

<p>$ data &gt; bar </p>

<p>$ chmod a-r foo bar {关闭所? </p>

<p>的读权限} </p>

<p>$ ls -l foo bar {验证其? </p>

<p>限} </p>

<p>--w--w---- l stevens 29 Jul 31 10:47 </p>

<p>ar </p>

<p>--w--w---- l stevens 29 Jul 31 10:47 </p>

<p>oo </p>

<p>$ a.out </p>

<p>运行程序4.3} </p>

<p>$ ls -l foo bar {检查文件的权限? </p>

<p>大小} </p>

<p>--w--w---- l stevens 0 Jul 31 10:47 bar </p>

<p>--w--w---- l stevens 0 Jul 31 10:47 </p>

<p>oo </p>

<p>可以看出存取权限没有改变,但是文件长度缩短了。 </p>

<p>4.6 目录的长度从来不会是0,因为它总是包含 .和 ..两项。符号连接的长</p>

<p>度指其 </p>

<p>路径名的包含的字符数,由于路径名中至少有一个字符,所以长度也不为0。</p>

<p>4.8 当创建新的core文件时,内核对其存取权限有一个默认设置,在本例中</p>

<p>是:r </p>

<p>w-r--r--。这一缺省值可能会也许不会被umask的值修改。Shell对创建的</p>

<p>重定向的 </p>

<p>新文件也有一个默认的访问权限,本例中为rw-rw-rw-。这个值总是被当前</p>

<p>的umas </p>

<p>k修改,在本例中umask为02。 </p>

<p>4.9 不能使用du的原因是它需要文件名或目录名作为参数,例如: </p>

<p>du tempfile </p>

<p>du . </p>

<p>只有当unlink函数返回时才释放tempfile的目录项,du命令没有计算仍然被</p>

<p>temp </p>

<p>file占用的空间。在本例中只能使用df命令察看文件系统中实际可用的自由</p>

<p>空间。 </p>

<p>4.10 如果被unlink的链接不是该文件的最后一个链接,该文件不会删除。</p>

<p>此时, </p>

<p>unlink函数更新文件的状态改变时间。如果是最后一个链接,该文件将被物</p>

<p>理删除 </p>

<p>。这时再去更新文件的状态改变时间就没有意义,因为包含文件所有信息的i</p>

<p>节点 </p>

<p>将会随着文件的删除而被释放。 </p>

<p>4.11 用opendir打开一个目录后,循环调用函数dopath。假设opendir使</p>

<p>用一个文 </p>

<p>件描述符,并且只有处理完目录后调用closedir才释放描述符,这就意味着</p>

<p>每次打 </p>

<p>开目录就要降一级使用另外一个描述符。所以系统可打开文件数就限制了文件</p>

<p>系统 </p>

<p>中树的深度。SVR4中的ftw允许调用者指定使用的描述符数,这隐含着该实现</p>

<p>可以 </p>

<p>关闭描述符并且重用它们。 </p>

<p>4.13 chroot函数用于辅助Internet文件传输程序(FTP)中的安全性。系统</p>

<p>中没有帐 </p>

<p>号的用户(也称为匿名FTP)放在一个单独的目录下,利用chroot将此目录当</p>

<p>作新的 </p>

<p>根目录就可以阻止用户访问此目录以外的文件。 </p>

<p>chroot也用于在另一台机器上构造一文件系统层次结构的一个副本,然后修</p>

<p>改此 </p>

<p>副本,但不更改原来的文件系统。这可用预测是新软件包装等场合。Chroot</p>

<p>只能有 </p>

<p>超级用户使用,一旦更改了一个进程的root,该进程及其后代进程就再也不</p>

<p>能恢复 </p>

<p>至原先的root。 </p>

<p>4.14 首先调用stat函数取得文件的三个时间值,然后调用utime设置期望的</p>

<p>值。我 </p>

<p>们不希望在调用utime改变的值就是stat中相应的值。 </p>

<p>4.15 finger(1)对邮箱调用stat函数,最近一次的修改时间是上一次接收</p>

<p>邮件的时 </p>

<p>间,最近访问时间是上一次读邮件的时间。 </p>

<p>4.16 对cpio来说,既可以改变文件的访问时间(st_atime)和修改时间</p>

<p>(st_mtime) </p>

<p>也可以都不改变。cpio的-a选项可以在读文件后重新设置文件的访问时间为</p>

<p>读文件 </p>

<p>前的时间,所以cpio可以不改变文件的访问时间。另一方面,-m选项将文件</p>

<p>的修改 </p>

<p>时间保存为原来的修改时间。 </p>

<p>对tar来说,在抽取文件时,其缺省方式是复原归档时的修改时间,但是-m选</p>

<p>项则 </p>

<p>将修改时间设置为抽取文件时的时间。无论tar在何种情况,文件的访问时间</p>

<p>均是 </p>

<p>抽取文件时的时间。 </p>

<p>由于不能修改状态改变时间(utime也只能改变访问时间和修改时间),所以没</p>

<p>有将 </p>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -