Linux Chapter5 Exercise
本科时期Linux 程序设计的实验文档整理。
一.实验内容
T1
1、 设计一个程序,要求打开文件“pass”,如果没有这个文件,新建此文件,权限设置为文件所有者具有只读权限。
实验步骤:
首先先使用im编辑好程序,程序具体的内容就不放在这里了,使用到的头文件和函数参数说明会写在下面。
编辑完程序我的目录里的全部文件是这样的:
运行程序:
发现目录文件夹里多出了一个pass的txt文件,虽然里面并不没有存储什么内容,但权限确实是拥有者只读了。
程序很简单,重点是记录的打开创建文件open函数。下面记录一下open的各种参数用法:
使用open需要包含的头文件:
1 |
函数原型:
1 | int open( const char * pathname, int flags); |
参数flags所有的用法:
这里只用到了其中的两个。
当新建文件时,mode应该填上去,我这里没有写东西,mode填写的是0400(所有者只读),如果后面要写东西,选择这个模式是没法写进文件里去的。
我在打开文件前还先检验了一下文件是否存在(包含unistd.h头文件),其实按照上面参数介绍来说,不这么做直接O_CREATE打开应该也是可以的。
2、 设计一个程序,要求新建一个文件“Hello”,利用write函数将“Linux下c语言程序设计”等字符串写入该文件中。
T2
实验步骤:
1 | g++ linux5T2 -o linux5T2 |
运行以后Hello的txt文件就生成了,但是还是要注意一点,这个地方如果权限mode设置不对或是忘了设置的话,Hello就没法打开(不可读),需要再改一遍权限为至少可读,我开始就犯了这样的错误。
出现的问题是写入的字符串后面多出了“\00\00”
使用im打开Hello.txt文件,发现文件末尾多出来了一个“@”
把代码发给了老师,老师说他没有出现这样的错误,一切正常,至今还比较迷惑,因为我也没有输入多余的换行或者是空格。
3、 设计一个程序,要求打开文件“pass”,如果没有这个文件,新建此文件,再读取系统文件“/etc/passwd”,将文件中的内容写入到“pass”文件中。
T3
实验步骤:
这个实验的步骤和上面的实验大同小异,一点差距就是把读到的文件内容直接写入目标文件。
1 | //循环将读取的的文件内容直接写入目标文件中 |
c++代码编辑完毕后,对程序进行编译执行。
1 | g++ linux5T3.C -o linux5T3 |
这个比较需要注意的还是路经问题,我开始时设置路径为“~/chap5/linux5T3/pass.txt”,结果创建文件总是失败,设置好完整路径就成功的运行了程序了。
修改成完整的文件路径:
打开程序执行后的源文件夹里生成的pass.txt文件,发现etc/passwd里面的内容已经复制进去。
4、 设计一个程序,要求打印系统目录/usr/include 下所有的文件和子目录的名字。
T4
实验步骤:
这道题主要是针对特殊文件-目录文件的操作:
目录文件是Linux中一种比较特殊的文件。它是Linux文件系统结构中骨架,对构成整个树型层次结构的Linux文件系统非常重要。对目录文件的操作可以使用mkdir函数、opendir函数、closedir函数、readdir函数和scandir函数等。
当然需要包含头文件:
1 |
编译运行:
1 | g++ linux5T4.C -o linux5T4 |
出现权限不足报错:Permission denied。
…仔细一看发现上面出现了的报错,并不是一般的权限不足,就是把“./linux5T4”写成了“./linux5T4.C”…以后不能再这样马虎了。
修改过来以后执行:
系统目录/usr/include 下所有的文件和子目录的名字被打印在Terminal中了。
5、 仿照例5.11,打开一个文件,测试文件有没有被其他进程加写锁或是读取锁,如果已经加了,写锁,那么直接退出,如果加了读取锁,那么继续等待。如果没有加锁,则对其加上写锁,写入“Linux环境下程序设计”,然后取消锁,将文件中的内容读出到屏幕上,退出。
T5
实验步骤:
实验分析:
例5.11的作用是:
打开文件后对其加上强制性的写入锁F_WRLCK,按回车后解锁F_UNLCK,然后加上读出锁F_RDLCK,按回车后再解锁F_UNLCK。
在例5.11中有一个出现了多次的重要函数fcntl:
fcntl是计算机中的一种函数,通过fcntl可以改变已打开的文件性质。
fcntl针对描述符提供控制。参数fd是被参数cmd操作的描述符。针对cmd的值,fcntl能够接受第三个参数int arg。
fcntl的返回值与命令有关。如果出错,所有命令都返回-1,如果成功则返回某个其他值。
我查找了fctnl函数常用的参数进行了整理记录:
| fcntl参数表格 | |
|---|---|
| 1 | F_DUPFD用来查找大于或等于参数arg的最小且仍未使用的文件描述符,并且复制参数fd的文件描述符。执行成功则返回新复制的文件描述符。新描述符与fd共享同一文件表项,但是新描述符有它自己的一套文件描述符标志,其中FD_CLOEXEC文件描述符标志被清除。 |
| 2 | F_GETFD取得close-on-exec旗标。若此旗标的FD_CLOEXEC位为0,代表在调用exec()相关函数时文件将不会关闭。 |
| 3 | F_SETFD 设置close-on-exec 旗标。该旗标以参数arg 的FD_CLOEXEC位决定。 |
| 4 | F_GETFL 取得文件描述符状态旗标,此旗标为open()的参数flags。 |
| 5 | F_SETFL 设置文件描述符状态旗标,参数arg为新旗标,但只允许O_APPEND、O_NONBLOCK和O_ASYNC位的改变,其他位的改变将不受影响。 |
| 6 | F_GETLK 取得文件锁定的状态。 |
| 7 | F_SETLK 设置文件锁定的状态。此时flcok 结构的l_type 值必须是F_RDLCK、F_WRLCK或F_UNLCK。如果无法建立锁定,则返回-1,错误代码为EACCES 或EAGAIN。 |
| 8 | F_SETLKW F_SETLK 作用相同,但是无法建立锁定时,此调用会一直等到锁定动作成功为止。若在等待锁定的过程中被信号中断时,会立即返回-1,错误代码为EINTR。 |
要实现本题的逻辑,只需要对例5.11的lock_set(...)函数内做一点修改即可。
对while循环的前半部分,即没有设置进程锁逻辑那部分代码进行修改:
打开两个终端,其中一个终端运行5-11中的代码程序,方便进行测试:
测试结果如下截图所示。
打开文件,检测到文件被加上了写入锁,则直接退出程序:
打开文件,未设置进程锁时,将字符串输出到终端屏幕上:
打开文件,检测到文件被加上了读取锁,则继续等待:
打开文件,检测到文件被加上了读取锁,则继续等待,直到读取锁被释放,再对其加上写锁,写入“Linux环境下程序设计”,然后取消锁,将文件中的内容读出到屏幕上:
二.实验总结
这次没有遇到什么技术性的错误,整理下这次作业用到的ppt上的知识点吧。
1.文件的读写操作
2.基于流的I/O操作
1)流的打开与关闭
基于输入/输出流机制的文件操作,叫做文件流(File Stream)。
fclose函数说明
2)格式化输入与输出
printf函数说明
fscanf函数说明
3.特殊文件的操作
opendir函数说明
readdir函数说明
三.实验感想
实验比较简单,只要做作业的时候头脑比较清醒,好好看一看老师文件包里面的PPT和示例程序,做下来还是比较快的,但前提就是头脑清醒,不然犯一些马虎错误就很痛苦了。