在Linux系统中,外存中的数据和程序都是以文件的方式保存,甚至对目录和各种设备的操作也都等同于文件的操作。
1.Linux系统文件的属性
文件是指有名字的一组相关信息的集合。文件系统是操作系统用来管理和保存文件的。不同的文件系统的数据结构和管理程序是不同的,Linux操作系统支持多种不同的文件系统。Linux的文件系统属于树形结构。文件系统的开始是从根目录(/)开始,不同的文件系统可以挂载在根文件系统下的不同子目录下。
Linux文件类型:普通文件、目录文件、符号链接文件、设备文件、管道文件、socket文件等。
下面的程序列出相应目录下的文件信息
函数原型 :int system(const char * string)
函数传入值:系统变量
函数返回值:执行成功则返回执行shell命令后的返回值,调用/bin/sh失败则返回127,其他失败原因则返回-1。
用ls命令长列表显示文件类型
命令 | 作用 |
普通文件 | 权限的10个字符中的第一位是“-"的文件 |
目录文件 | 权限的10个字符中的第一位是"d"的文件 |
硬链接文件 | 除了显示的文件数量,其他都和某个普通文件一模一样的文件 |
软链接文件 | 权限的10个字符中的第一位是“l"的文件 |
块设备文件 | 权限的10个字符中的第一位是“b"的文件 |
socket文件 | 权限的10个字符中的第一位是“s"的文件 |
字符设备文件 | 权限的10个字符中的第一位是“c"的文件 |
管道文件 | 权限的10个字符中的第一位是“p"的文件 |
setUid可执行文件 | 权限的10个字符中的第四位是“s"的文件 |
setGid可执行文件 | 权限的10个字符中的第七位是“s"的文件 |
setUid加setGid文件 | 权限的10个字符中的第四位和第七位都是“l"的文件 |
下面设计一个程序,把”/etc/passwd"文件权限设置成文件所有者可读可写,所有其他用户为只读权限。
设计一个程序,要求设置文件系统与目录的权限掩码
文件的权限 = 预设的文件权限- 权限掩码
函数chmod用来改变文件权限,它的函数原型为: int chmod(const * path,mode_t mode);根据参数mode权限来更改参数path指定文件的权限,权限更改成功返回0,失败则返回-1
mode参数说明如下:
参数:mode | 说明 |
S_IRUSR | 拥有着具有读取权限 |
S_IWUSR | 拥有着具有写入权限 |
S_IXUSR | 拥有着具有执行权限 |
S_IRGRP | 组具有读取权限 |
S_IWGRP | 组具有写入权限 |
S_IXGRP | 组具有执行权限 |
S_IROTH | 其他用户具有读取权限 |
S_IWOTH | 其他用户具有写入权限 |
S_IXOTH | 其他用户具有执行权限 |
所需头文件: #include<sys/types.h> 、#include<sys/stat.h>
函数功能:设置建立新文件时的权限掩码
函数原型:mode_t umask(mode_t mask)
函数传入值:4位八进制数
函数返回值:返回值为原先系统的umask值
注意:建立文件时,该文件的真正权限为0666-mask值;建立文件夹时,该文件夹的真正权限是0777-mask值
在linux系统中,通过定义stat结构体来存放文件的各种属性:
struct stat
{
dev_t st_dev;/*文件所在设备的ID*/
ino_t st_ino;/*索引节点号*/
mode_t st_mode;/*文件保护模式*/
nlink_t st_nlink;/*用户号,针对设备文件*/
uid_t st_uid;/*用户ID*/
gid_t st_gid;/*组ID*/
dev_t st_rdev;/*设备号,针对设备文件*/
off_t st_size;/*文件字节数*/
unsigned long st_bikesize;/*系统块的大小*/
unsigned long st_blocks;/*文件所占块数*/
time_t st_atime;/*最后一次访问时间*/
time_t st_mtime;/*最后一次修改时间*/
time_t st_ctime;/*最后一次改变时间(指属性)*/
};
设计一个程序,应用系统函数stat获取"/etc/passwd"文件的大小
stat函数说明:
函数原型:int stat(const * file_name,struct stat *buf),将参数file_name所指的文件状态复制到参数buf所指的结构中,执行成功返回0,失败返回-1.
2.不带缓存的文件I/O操作
Linux系统把目录、设备等的操作,都等同于文件的操作。Linux系统通过文件描述符来区分和应用特定的文件。文件描述符是一个非负的整数,是一个索引值,指向内核中每个进程打开文件表。基于文件描述符的文件操作主要有:不带缓存的文件I/O操作和带缓存的文件流I/O操作。
不带缓存的文件I/O操作主要用到下表中的函数
函数 | 作用 |
creat | 创建文件 |
open | 打开或创建文件 |
close | 关闭文件 |
read | 读文件 |
write | 写文件 |
lseek | 移动文件的读写位置 |
flock | 锁定文件或解除锁定(用于文件加建议性锁) |
fcnd | 文件描述符操作(用于文件加强制性锁) |
函数原型 int creat(const char * pathname,mode_t mode);函数的两个参数分别用来建立文件的访问路径和设置新增文件的权限,正确返回0,错误则返回-1
使用open函数打开一个文件,如果文件不存在则创建一个文件,使用close函数关闭文件
文件的读写操作:
read函数用于在指定的文件描述符中读出数据,write函数用于向打开的文件写数据,写数据从文件当前位置开始。seek函数用于在指定的文件描述符中将文件指针定位到相应的位置。
下面的程序从终端读数据再写会到终端
下面的程序利用read函数读取"/etc/passwd"的内容,然后使用write函数写到目标文件中
下面的程序打开当前终端文件/dev/tty,在打开时指定O_NONBLOCK标志。程序运行每隔6秒等待用户从终端输入,等待30秒,30秒后程序继续执行主程序,输出图形结束。
可以使用fcntl函数改变一个已打开文件的属性,可以重新设置读、写、追加、非阻塞等标志,使用函数fcntl通过F_GETFL,F_SETFL可以分别用于读取、设置文件的属性,能够更改的文件标志有O_APPEND,O_ASYNC,O_DIRECT,O_NOATIME和O_NONBLOCK.
Linux是多用户操作系统,当多个用户对同一文件操作时,就需要给文件加锁,锁分为建议性锁和强制性锁。给文件加建议性锁的是flock函数,给文件加强制性锁的是fcntl函数。
下面的程序先用open函数打开(创建)文件“locfile”;接着调用自定义函数lock_set:先传递参数“F_WRLCK"给该文件加锁,并打印输出给文件加锁进程的进程号,然后先传递参数”F_UNLCK“给文件解锁,并打印输出给文件解锁进程的进程号;在自定义函数lock_set给文件上锁语句前,加上判断文件是否上锁的语句,如果文件已经上锁,打印输出给文件上锁进程的进程号。
int flock(int id,int operation),函数用于锁定文件或解除锁定(用于文件夹建议性锁),而函数fcntl用于给文件加强制性锁,成功返回0,失败返回-1
3.带缓存的流文件I/O操作
带缓存的 流文件I/O操作,是在内存开辟一个“缓存区”,为程序的每一个文件使用。当执行读文件操作时,从磁盘文件将数据先读入内存“缓冲区”,装满后再从内存“缓冲区”依次读入接受的变量。当执行写文件操作时,先将数据写入内存“缓存区”,待内存“缓存区”装满后再写入文件。
带缓存的文件I/O操作主要用到的函数:
函数 | 作用 |
fopen | 打开或创建文件 |
fclose | 关闭文件 |
fgetc | 由文件读取一个字符 |
fputc | 将一指定字符写入文件流中 |
fgets | 由文件中读取一字符串 |
fputs | 将一指定的字符串写入文件内 |
fread | 从文件流成块读取数据 |
fwrite | 将数据成块的写入文件流 |
fseek | 移动文件流的读写位置 |
rewind | 移动文件流的读写位置为文件开头 |
ftell | 取得文件流的读取位置 |
带缓存的基于输入输出流机制的文件操作时,打开文件用fopen函数,关闭文件用fclose函数。
带缓存的基于输入输出流机制的文件操作时,读字符用fgetc函数,写字符用fputc函数
带缓存的基于输入输出流机制的文件操作时,读字符串用fgets函数,写字符串用fputs函数
下面的fwrite2程序把三个人的姓名和账号月信息通过一次流文件I/O操作写入文件testfwrite中,而程序fread负责读取文件信息。把快信息写入文件用fwrite函数,从文件读取信息用fread函数。
函数功能:将数据写入到文件流
函数原型:size_t fwrite(const void * ptr,size_t size,size_t nmemb,FILE * stream);
函数传入值:ptr:欲写入的数据地址 size:字符串长度 nmemb:字符串数目 stream:一个文件流
函数返回值:成功则返回实际写入的nmemb数目,失败则返回EOF
函数功能:从文件流读取数据
函数原型:size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream);
函数传入值:ptr:从文件读取的内容存放到ptr所指的内存首地址 size:字符串长度 nmemb:字符串数目 stream:一个文件流
函数返回值:成功则返回实际写入的nmemb数目,失败则返回EOF
下面的程序先调用fseek函数定位到距文件开头SEEK_SET位移量为10,调用ftell函数取得文件流的偏移量并输出,然后调用fseek函数定位到距文件结尾SEEK_END位移量为0,调用ftell函数取得文件流的偏移量并输出;最后调用rewind函数重设文件流的读写位置为文件开头,调用ftell函数取得文件流的偏移量并输出。
4.特殊文件的操作
目录文件的操作:
opendir函数:打开目标文件
readdir函数:读取目录文件
closedir函数:关闭目录文件
下面的程序打印系统目录“/etc/rc.d"中的所有的目录结构
下面的程序要求用递归的方法列出某一目录下的全部文件的大小和文件夹及创建日期,包括子文件和子文件夹。
链接文件的操作:symlink函数用于建立软链接