一、文件的一些基础知识:
Linux里面一切都是文件,那从哪里看出是什么文件并具有哪些属性呢?
通过指令:ls -l的结果的第一位标识位看出来:
(1)-表示普通文件;
(2)d表示文件夹;
(3)c表示字符设备文件;
(4)b表示块设备文件;
(5)s表示套接字socket文件;
(6) l表示符号链接,即软链接 通过名字指向另外一个文件
(7)p表示该文件为命令管道文件。与shell编程有关的文件。
关于软连接的相关概念:
链接文件的概念类似于windows里的快捷方式。多个链接文件同时指向一个“源文件”。链接文件分为硬链接或符号链接两种。
在Linux的文件系统中,保存在磁盘分区中的文件不管是什么类型都给它分配一个编号,称为索引节点号inode 。软连接,其实就是新建立一个文件,这个文件就是专门用来指向别的文件的(那就和windows 下的快捷方式的那个文件有很接近的意味)。软连接产生的是一个新的文件,但这个文件的作用就是专门指向某个文件的,删了这个软连接文件,那就等于不需要这个连接,和原来的存在的实体原文件没有任何关系,但删除原来的文件,则相应的软连接不可用(cat那个软链接文件,则提示“没有该文件或目录“)
软链接可以跨文件系统,硬链接不可以;软链接可以对一个不存在的文件名(filename)进行链接(当然此时如果你vi这个软链接文件,linux会自动新建一个文件名为filename的文件),硬链接不可以(其文件必须存在,inode必须存在);软链接可以对目录进行连接,硬链接不可以。两种链接都可以通过命令 ln 来创建。ln 默认创建的是硬链接。使用 -s 开关可以创建软链接
第一位标识位后面9个字母表示该文件或目录的权限位。
r表是读 (Read) 、w表示写 (Write) 、x表示执行 (eXecute)
其中前三个表示文件拥有者的权限,中间三个表示文件所属组拥有的权限,最后三个表示其他用户拥有的权限。
比如:
-rw-r--r-- 1 root root 762 07-29 18:19 exit
表示文件的拥有者root对文件有读写权限,其他人(同组用户和其他用户只有读的权限)
其中:rwx也可以用数字来代替
r ------------4
w -----------2
x ------------1
- ------------0
可以通过chmod指令来为文件增加权限
-rw------- (600) 只有所有者才有读和写的权限
-rw-r--r-- (644) 只有所有者才有读和写的权限,组群和其他人只有读的权限
-rwx------ (700) 只有所有者才有读,写,执行的权限
-rwxr-xr-x (755) 只有所有者才有读,写,执行的权限,组群和其他人只有读和执行的权限
-rwx--x--x (711) 只有所有者才有读,写,执行的权限,组群和其他人只有执行的权限
-rw-rw-rw- (666) 每个人都有读写的权限
-rwxrwxrwx (777) 每个人都有读写和执行的权限
如: chmod 777 filename 表示为文件添加每个人都有读写和执行的权限。
第二字段表示文件硬链接数
-rw-r--r-- 1 root root 762 07-29 18:19 exit
如果一个文件不是目录,此时这一字段表示这个文件所具有的硬链接数,
第二字段的值为1,说明这个文件只有exit这一个文件名。即只有一个指向该链接的硬链接。。
如果使用ln,做一个指向该文件的硬链接再查看该文件,该文件的第二字段就会变成二。
第三点字段:文件(目录)拥有者3字段:文件(目录)拥有者
lrwxrwxrwx 1 root root 4 08-03 08:27 bexit -> exit
该字段表示此文件是属于哪个用户。linux类系统都是多用户系统,每个文件都有它的拥有者。只有文件的拥有者才具有改动文件属性的权利。当然, root用户具有改动任何文件属性的权利。对于一个目录来说,只有拥有该目录的用户,或者具有写权限的用户才有在目录下创建文件的权利
如果某一个用户因为某种原因,被删除,而该用户的文件还存在,那么用ls -l 查看该文件将显示一个代表用户存在前ID号的数字。
第4字段:文件(目录)拥有者所在的组
一个用户可以加入很多个组,但是其中有一个是主组,就是显示在第4字段的名称。
可以在useradd的时候用-g指定该用户所在的主组,用-G指定其他组
后面字段就不介绍了,就记一点如果是一个符号链接,那么会有一个 “->" 箭头符号,后面根一个它指向的文件名,如
lrwxrwxrwx 1 root root 4 08-03 08:27 bexit -> exit
二、文件的打开/创建。
API:
#include
int open(const char *pathname, int flag,...);
当使用系统调用open打开一个文件时,操作系统会创建一些数据结构来表示这个被打开的文件。为了能够找到这些数据结构,在进程中,代码会为这个打开的文件分配一个文件描述符fd(File Descriptor)。文件描述符就是用来区分一个进程打开的多个文件的。它的作用域就是当前进程,出了当前进程这个文件描述符就没有意义了。
补充说明:
文件平时是存放在块设备中的文件系统文件中的,我们把这种文件叫做静态文件,当我们取open打开一个文件时,linux内核做的操作包括:内核在进程中建立一个打开的数据结构,记录下我们打开的这个文件;内核在内存张申请一段内存,并将静态文件的内容从块设备读到内核中特定的地址管理存放(叫动态文件)。
打开文件以后,对这个文件的读写操作,都是针对内存中的这一份动态文件的,而并不是对静态文件的。当然我们对动态文件进行读写以后,此时内存中动态文件和块设备文件中的静态文件就不同步了,当我们close关闭动态文件时,close内部将内存中的动态文件的内容取更新块设备中的静态文件。所以最后读写完成后,一定要关闭文件,否则会造成文件损坏。
文件描述符fd
文件描述符在形式上 是一个非负整数。它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕文件描述符展开。
习惯上,标准输入(standard input)的文件描述符是 0,标准输出(standard output)是 1,标准错误(standard error)是 2。
0,1,2对应的物理设备一一般是:键盘,显示器,显示器。
所以通常当我们成功打开文件时,返回的fd都是从3起。
若打开失败,文件描述符fd等于-1;
pathname:打开文件的路径可以是绝对路径,也可以是相对路径。
flag:
O_RDONLY 只读打开 O_WRONLY 只写打开 O_RDWR 可读可写打开
这三个只能选择一个
下列常数是可选择的:
O_CREAT 若文件不存在则创建它。使用此选项时,需要同时说明第三个参数mode,用其说明该新文件的存取许可权限。
O_EXCL 如果同时指定了OCREAT,而文件已经存在,则出错。 (可用来判断文件是否存在)
O_APPEND 每次写时都加到文件的尾端。
O_TRUNC 属性去打开文件时,如果这个文件中本来是有内容的,而且为只读或只写成功打开,则将其长度截短为0。(即将原文件的内容清除)
如:
fd = open("./filename", O_RDWR|O_CREAT, 0777);
表示打开当前文件下的filename,以可读可写的方式打开,如果没有filename这个文件就创建,文件权限为777(可参考上面基础知识部分)。0777的0表示可参考
http://chen498402552-163-com.iteye.com/blog/1164407
三、文件的写入。
API:
#include
ssize_t write(fd, const void *buf, size_t count);
write()会把参数buf所指的内存写入count个字节到参数fd所指的文件内。
返回值:如果顺利write()会返回实际写入的字节数(len)。当有错误发生时则返回-1,错误代码存入errno中。
附加说明:
write()函数返回值一般无0,只有当如下情况发生时才会返回0:write(fp, p1+len, (strlen(p1)-len))中第三参数为0,此时write()什么也不做,只返回0。
write()函数从buf写数据到fd中时,若buf中数据无法一次性读完,那么第二次读buf中数据时,其读位置指针(也就是第二个参数buf)不会自动移动,需要程序员来控制,而不是简单的将buf首地址填入第二参数即可。如可按如下格式实现读位置移动:write(fp, p1+len, (strlen(p1)-len))。 这样write第二次循环时便会从p1+len处写数据到fp, 之后的也一样。由此类推,直至(strlen(p1)-len)变为0。
附加说明:原文链接:https://blog.csdn.net/hhhlizhao/article/details/71552588
四、文件的读取。
API:
ssize_t read(int fd, void * buf, size_t count);
read()会把参数fd所指的文件传送count 个字节到buf 指针所指的内存中。
返回值:返回值为实际读取到的字节数, 如果返回0, 表示已到达文件尾或是无可读取的数据。
读取失败则返回-1。
附加说明:读常规文件时,在读到count个字节之前已到达文件末尾。例如,距文件末尾还有50个字节而请求读100个字节,则read返回50,下次read将返回0。(这是因为光标的原因)
五、文件光标的相关操作
API:
#include
#include
off_t lseek(int fd, off_t offset, int whence);
返回值:新的偏移量(成功),-1(失败)
offset:光标的偏移值,相对于第三个参数。offset
为正则向文件末尾移动(向前移),为负数则向文件头部(向后移)。
whence:有三个选项
SEEK_SET
:
从文件头部开始偏移offset
个字节。 SEEK_CUR
:
从文件当前读写的指针位置开始,增加offset
个字节的偏移量。 SEEK_END
:
文件偏移量设置为文件的大小加上偏移量字节。(即从文件内容的末尾开始偏移)
可以利用lseek函数的返回值来计算文件的大小:
int main()
{
int fd;
int filesize;
fd = open("./filename", O_RDWR);
if(fd == -1){
printf("open failed!\n");
perror("");
}
filesize = lseek(fd, 0 , SEEK_END);
printf("filename's size: %d", filesize);
close(fd);
return 0;
}
六、文件的关闭
close(fd); 就不记录了