一、系统调用
系统调用 是内核提供给应用层的一系列接口函数,应用层调用接口函数让内核完成一定的任务。
二、常用文件操作函数
标C:fopen fread fwrite fgets fseek fclose(基于有缓冲区的)
UC: open read write lseek close (非缓冲区)
文件操作:
1.打开文件 open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
pathname :文件路径
flags :标志位
O_RDONLY:以只读方式打开文件
O_WRONLY:以只写方式打开文件
O_RDWR:以读写方式打开文件
O_CREAT:如果改文件不存在,就创建一个新的文件,并用第三个参数为其设置权限
O_EXCL:如果使用O_CREAT时文件存在,则返回错误消息。这一参数可测试文件是否存在。此时open是原子操作,防止多个进程同时创建同一个文件
O_NOCTTY:使用本参数时,若文件为终端,那么该终端不会成为调用open()的那个进程的控制终端
O_TRUNC:若文件已经存在,那么会删除文件中的全部原有数据,并且设置文件大小为0
O_APPEND:以添加方式打开文件,在打开文件的同时,文件指针指向文件的末尾,即将写入的数据添加到文件的末尾
O_NONBLOCK: 如果pathname指的是一个FIFO、一个块特殊文件或一个字符特殊文件,则此选择项为此文件的本次打开操作和后续的I/O操作设置非阻塞方式。
O_SYNC:使每次write都等到物理I/O操作完成。
O_RSYNC:read 等待所有写入同一区域的写操作完成后再进行
在open()函数中,falgs参数可以通过“|”组合构成,但前3个标准常量(O_RDONLY,O_WRONLY,和O_RDWR)不能互相组合。
mode:被打开文件的存取权限,可以用两种方法表示,可以用一组宏定义:S_I(R/W/X)(USR/GRP/OTH),其中R/W/X表示读写执行权限,
USR/GRP/OTH分别表示文件的所有者/文件所属组/其他用户,如S_IRUUR|S_IWUUR|S_IXUUR,(-rex------),也可用八进制800表示同样的权限,如:
mode:文件权限 0644(可读可写)
0表示没有权限,1表示可执行权限,2表示可写权限,4表示可读权限,然后将其相加。
返回值:
成功:返回文件描述符(一个整数)
失败:返回-1
2.读写操作 read write
read:
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
fd:文件描述符
buf:存放数据缓冲区
count:要读的字节个数,以字节为单位
返回值:成功返回读的字节个数,到文件末尾返回0.出错返回-1。
write:
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
基本跟read函数一样。
返回值:成功返回真正写到文件当中字节的个数,出错返回-1。
3.关闭文件 close
#include <unistd.h>
int close(int fd);
注意:操作文件时尽量不要边读边写,最好先写,写完关闭,再以读的方式打开。
三、文件位置指针
记录了打开的文件读写位置
操作文件位置指针 lseek
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fildes, off_t offset, int whence);
fildes:文件描述符
offset:移动的字节个数 正数向右 负数向左移动
whence:相对位置
SEEK_SET 0 //文件开头
SEEK_CUR 1 //从当前位置
SEEK_END 2 //从文件末尾
返回值:返回文件位置指针所在的文件位置(即第几个字节),失败返回-1。
例:lseek(fd,0,SEEK_END); //求文件大小
四、文件描述符
文件描述符表,(其实就是个指针数组),每运行一个程序,系统会给程序建立一个文件描述符表,它记录了程序打开的所有文件描述符。每打开一个文件,会把文件结构体的地址写到表里面,然后返回文件描述符(文件描述符可以理解为序号、数组下标、一个唯一对应的整型数),每个程序最多打开1024个文件。
1.每个程序运行时都会默认打开三个文件描述符,即标准输入,标准输出,标准错误。
标准C stdin stdout stderr
UC STDIN_FILENO STDOUT_FILENO STDERR_FILENO
2.文件描述符的复制 dup
#include <unistd.h>
int dup(int oldfd); 随机返回新的描述符
int dup2(int oldfd, int newfd); 返回指定新文件描述符
参数:
oldfd : 源文件描述符
newfd : 新文件描述符
返回值:成功返回新的文件描述符,失败返回-1;
dup和普通的赋值的区别:当你fd2=fd1;都指向一个文件,然后当你close(fd1),fd2也同时失效。相当于整个文件与文件描述符数组的关系切断了。而你用dup的时候,即使关掉一个close(fd1),fd2依然可以用。
3.文件锁
在多进程当中,多个进程对同一个文件读写操作,可能造成数据的冲突。所以引入了文件锁,对正在操作的文件进行保护。
文件锁分为读锁和写锁
当一个进程在操作文件之前对文件加读锁,其他进程再加读锁可以加成功(即可以同时读)。但是其他进程加写锁是不成功的。
当一个进程对文件加了写锁,其他进程加读锁和写锁都不成功。
文件锁是影响了其他进程是否能够加锁成功,但不影响其他进程对文件的读写操作。(也就是说需要大家都遵守规定。如果某进程不遵守,你也没办法。所以某种意义上文件锁对于不遵守规定的人并没有什么卵用)
fcntl ( )+锁结构体
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
参数:
fd:文件描述符
cmd : F_DUPFD //复制文件描述符
F_GETFD //获取文件描述符标志位
F_SETFD //设置文件描述符标志位
F_GETFL //获取文件状态标志位
F_SETFL //设置文件状态标志位
F_GETLK //获取锁
F_SETLK //设置锁 非阻塞
F_SETLKW //设置锁 阻塞(即等待)
lock:
struct flock
{
short l_type; /*(锁类型) Type of lock: F_RDLCK,
F_WRLCK, F_UNLCK(解锁) */
short l_whence; /* 加锁的相对位置:
SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* 距相对位置差多少,即加锁的实际开 始位置*/
off_t l_len; /* 加锁区域的长度 */若上个参数和这 个参数均为0,则表示给整个文件加锁。
pid_t l_pid; /*一般赋-1 PID of process blocking our lock (F_GETLK only) */
...
};
返回值:成功返回0;失败返回-1。
五、获取文件状态
fstat stat lstat
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char *path, struct stat *buf);
参数:
path:文件路径
filedes:文件描述符
返回值成功是0,失败-1.
struct stat {
dev_t st_dev; /* 设备号 */
ino_t st_ino; /* 设备节点号 */
mode_t st_mode; /* 权限*/
nlink_t st_nlink; /* 硬链接个数 */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* 文件大小 in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of blocks allocated */
time_t st_atime; /*最近访问时间*/
time_t st_mtime; /*最近更改时间*/
time_t st_ctime; /* 最近文件状态改变时间*/
};
通过st_mode判断文件类型
S_ISREG(m) 普通文件?
S_ISDIR(m) 目录文件?
S_ISCHR(m) 字符文件?
S_ISBLK(m) 块设备?
S_ISFIFO(m) 管道文件?
S_ISLNK(m) 是否是链接文件?(Not in POSIX.1-1996.)
S_ISSOCK(m) 是否是套接字? (Not in POSIX.1-1996.)
S_IFMT 0170000 bitmask for the file type bitfields
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 FIFO
S_ISUID 0004000 set UID bit
S_ISGID 0002000 set-group-ID bit (see below)
S_ISVTX 0001000 sticky bit (see below)
S_IRWXU 00700 mask for file ownepermissions
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 mask for group permissions
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 mask for permissions for others (not in group)
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have executepermission