文件,除了本身包含的内容外,还有一个名字和一些属性,即“管理信息”-包括文件的创建、修改日期和他的访问权限,这些属性的被保存在文件的inode节点中。
删除文件名就等于删除与之对应的链接
使用ln命令在不同的目录中创建指向同一个文件的链接
删除一个文件时,实际是删除了该文件对应的目录项,同时指向该文件的链接数减1
drwxrwxr-x 2用户名组
为0就表示该节点以及指向的数据不再被使用
磁盘上的相应位置就会被标记为可用空间
cd ~进入家目录
cd -user(-用户名)进入他人的家目录
每个用户的家目录通常是一个上层目录的子目录
甚至硬件设备在Linux中通常也被映射为文件。
使用如下命令挂载驱动设备
mount -t iso9660 /dev/hdc/mnt/cdrom
cd/mnt/cdrom
比较重要的设备文件
/dev/console控制台
/dev/tty 控制终端
/dev/null 空设备
设备分为字符设备和块设备,两者区别在于访问设备时是否需要一次读一整块,一般情况下块设备是那些支持某些类型文件系统的设备,例如硬盘。
/dev目录中的设备文件用法都是相同的,都可以被打开,读,写和关闭。
下面是用于访问设备驱动程序的底层函数(系统调用)
open:打开文件或设备。
read:从打开的文件或设备里读数据。
write:向文件或设备写数据。
close:关闭文件或设备。
ioctl:把控制信息传递给设备驱动程序。
系统调用的性能开销比函数调用要大。执行系统调用时,linux必须从运行用户代码切换到执行内核代码,然后返回用户代码
硬件会限制底层系统调用一次所能读写的数据块大小。
当一个程序运行时,一般会有3个已经打开的文件描述符:
0:标准输入
1:标准输出
2:标准错误
write系统调用
函数返回0,未写入任何数据。
返回-1,出现错误。
错误代码保存在全局变量errno中。
下面是write系统调用的原型。
#include<unistd.h>
size_t write(int fileds,const void *buf,size_t nbytes);
size_t read(int fileds,void *buf,size_t nbytes);
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
int open(const char *path,int oflags);
int open(const char *path,int flags,mode_t mode);
模式
O_RDONLY以只读方式打开
O_WRONLY以只写方式打开
O_RDWR以读写方式打开
open调用时在oflags参数中包括下列可选模式的组合
O_APPEND:把写入数据追加在文件的末尾
O_TRUNC:把文件长度设置为0,丢弃已有的内容
O_CREAT:如果需要,就按参数mode中给出的访问模式创建文件
O_EXCL:与O_CREAT一起使用,确保调用者创建出来的文件,open调用是一个原子操作。
一个运行中的程序能够同时打开的文件数是有限制的,这个限制是由limits.h头文件中的常量OPNE_MAX定义的
访问权限的初始值
open函数调用中第三个参数mode是几个标志按位或后得到的。这些标志在文件sys/stat.h中定义
S_IRUSR:读权限,文件属主。
S_IWUSR:写权限,文件属主。
S_IXUSR:执行权限,文件属主。
S_IRGRP:读权限,文件属组。
S_IWGRP:写权限,文件属组。
S_IXGRP:执行权限,文件所属组。
S_ROTH:读权限,其他用户。
S_IWOTH:写权限,其他用户。
S_IXOTH:执行权限,其他用户。
#include<unistd.h>
int octl(int filds,int cmd,...);
ioctl对描述符filds引用的对象执行cmd参数给出的操作,例如:在linux的如下调用将打开键盘上的LED灯。
ioctl(tty_fd,KDSETLED,LED_NUM|LED_CAP|LED_SCR);
#include<unistd.h>
#include<sys/stat.h>
#inlcude<fcntl.h>
#include<stdlib.h>
int main()
{
char block[1024];
int in,out;
int nread;
in = open("file.in",O_RDONLY);
out = open("file.out",O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR);
while(nread = read(in,block,sizeof(block)) == 1)
write(out,block,nread);
exit(0);
}
TIMEFORMAT="" time ./a.out
TIMEFORMAT变量来重置默认的POSIX时间输出格式。
其他与文件管理有关的系统调用
lseek系统调用对文件描述符fildes的读写指针进行设置。也就是说。设置文件的下一个读写位置。
#include<unistd.h>
#include<sys/types.h>
off_t lseek(int fildes,off_t offset,int whence);
offset参数用来指定位置,而whence参数定义该偏移值的用法。
whence可以取下列值之一。
SEEK_SET:offset是一个绝对位置。
SEEK_CUR:offset是相对于当前位置的一个相对位置。
SEEK_END:offset是相对于文件尾的一个相对位置。
lseek放回从文件头到文件指针被设置出的字节偏移量,失败返回-1。
fstat,stat和lstat系统调用
函数原型
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
int fstat(int fildes,struct stat *buf);
int stat(const char *path,struct stat *buf);
int lstat(const char *path,struct stat *buf);
struct stat
st_mode 文件权限和文件类型信息
st_ino 与该文件关联的inode
st_dec保存文件的设备
st_uid 文件属主的UID号
st_gid文件属主的GID号
st_atime 文件上一个次被访问的时间
st_ctime 文件的权限,属主,组或内容上一个被改变的时间
st_mtime 文件的内容上一次被修改的时间
st_link 该文件上硬链接的个数
文件类型的标志,stat结构体中st_mode的宏定义
S_IFBLK:一个特殊的快设备
S_IFDIR:一个目录
S_IFCHR:一个特殊的字符设备
S_IFIFO:一个FIFO(命名管道)
S_IFREG:一个普通文件
S_FLNK:一个符号链接
以下其他模式标志
S_ISUID:文件设置了SUID位
S_ISGID:文件设置了SGID位
解释st_mode标志的掩码
S_IFMT:文件类型
S_IRWXU:属主的读、写、执行权限
S_IRWXG:属组的读、写、执行权限
S_IRWXO:其他用户的读、写、执行权限
帮助确定文件类型的宏定义
S_ISBLK:测试是否是特殊的块设备文件
S_ISCHR:测试是否是特殊的字符设备文件
S_ISDIR:测试是否是目录
S_ISFIFO:测试是否是普通文件
S_ISREG:测试是否是普通文件
S_ISLNK:测试是否是符号链接
测试一个文件代表的不是一个目录,设置了属主的执行权限,并且不再有其他权限
struct stat statbuf;
mode_t modes;
stat("filename",&statbuf);
modes = statbuf.st_mode;
if(!IS_ISDIR(modes) && (modes & S_IRWXU) == S_IXUSR)
..
dup和dup2系统调用
dup系统调用提供了一种复制文件描述符的方法
函数原型
#include<unistd.h>
int dup(int fildes);
int dup2(int filds,int files2);
在标准I/O库中,与底层文件描述符对应的是流,他被实现为指向结构FILE的指针。
在启动程序时,有3个文件流是自动被打开的,他们是stdin,stdout,stderr。
标准I/O库中的下列函数
fopen,fclose
fread,fwrite
fflush
fseek
fgetc,getc,getchar
fputc,putc,putchar
fgets,gets
printf,fprintf,sprintf
scanf,fscanf,sscanf
fopen函数
函数原型
#include<stdio.h>
FILE *fopen(const char *filename,const char *mode);
fopen函数mode参数指定文件的打开方式。
"r"或"rb":以只读方式打开
"w"或"wb":以写方式打开,并把文件长度截断为零
"a"或"ab":以写方式打开,新内容追加在文件尾
"r+"或"rb+"或"r+b":以更新方式打开(读和写)
"w+"或"wb+"或"w+b":以更新方式打开,并把文件长度截断为零
"a+"或"ab+"或"a+b":以更新方式打开,新内容追加在文件尾
fread函数
从一个文件流里读取数据,数据文件从文件stream读到ptr由指向的数据缓存区
#include<stdio.h>
size_t fread(void *ptr,size_t size,size_t nitems,FILE *stream);
size参数指定每个数据记录的长度
计数器nitems给出要传输的记录个数
返回值是成功读到数据缓存区的记录个数(而不是字节数),当达到文件尾时,返回值可能小于nitems,甚至可以是0
fwrite函数
返回值是成功写入的记录个数
#include<stdio.h>
size_t fwrite(const void *ptr,size_t size,size_t nitems,FILE *stream);
fclose函数
关闭指定的文件流stream,使所有尚未写出的数据都写出。
#include<stdio.h>
int fclose(FILE *stream);
fflush函数
作用是吧文件流的所有未写出的数据立刻写出。
调用fclose函数应该隐含执行了一次flush操作
#include<stdio.h>
int fflush(FILE *stream);
fseek函数
0表示成功,-1表示失败并设置errno指出错误。
#inlcude<stdio.h>
int fseek(FILE *stream,long int offset,int whence);
fgetc,getc和getchar函数
#include<stdio.h>
int fgetc(FILE *stream);
int getc(FILE *stream);
int getchar();
fputc,putc和putchar函数
把一个字符写到一个输出文件流中,返回写入的值,如果失败,则返回EOF。
#include<stdio.h>
int fputc(int c,FILE *stream);
int putc(int c,FILE *stream);
int putchar(int c);
fgetc和gets函数
fgets函数从输入文件流stream里读取一个字符串
#include<stdio.h>
char *fgets(char *s,int n,FILE *stream);
char *gets(char *s);
格式化输入和输出
printf,fprintf和sprintf函数
#inlcude<stdio.h>
int printf(const char *format,...);
int sprintf(char *s,const char *format,...);
int fprintf(FILE *stream,const char *format,..);
scanf,fscanf和sscanf函数
#include<stdio.h>
int scanf(const char *format,...);
int fscanf(FILE *stream,const char *format,....);
int sscanf(const char *s,const char *format,...);