一、常用函数
fopen:
FILE *fopen(const char *filename, const char *mode);
fread:
size_t fread(void *ptz, size_t size, size_t nitems, FILE *stream);
fwrite:
size_t fwrite(const void *ptz, size_t size, size_t nitems, FILE *stream);
fclose:
int fclose(FILE *stream);
fflush:
int fflush(FILE *stream);
fseek:
int fseek(FILE *stream, long int offset, int where);
fgetc,getc,getchar
int fgetc(FILE *stream);
int fgetc(FILE *stream);
int getchar(); //标准输入
fputc,putc,putchar
int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
fgets,gets
char *fgets(char *s, int n, FILE *stream);
fputs,puts
int *fputs(char *s, FILE *stream);
int *puts(char *s);
在同级目录下建立一个文件file.in,用下面的代码实现文件拷贝(函数的参数可以使用man查找,或者参考libc文档)
#include
int main(){
char c;
FILE *pin, *pout;
//open file
pin = fopen("file.in", "r");
pout = fopen("file.out", "w+");
while(c = fgetc(pin) != EOF){
fputc(c, pout);
}
fclose(pin);
fclose(pout);
return 0;
}
当我们很清楚我们的物理资源和不想让一些缓存来干扰我们的时候(实时性要求高的地方)就可以使用底层的I/O操作,大部分情况下使用标准I/O操作就可以到达我们的要求。
二、文件锁定
假如有一个文件a,如果进程A在操作(修改)的时候,进程B有可能正在读文件,这样就会出现问题(有点像线程同步问题)。文件的锁定方式有文件型的记录型的两种,对文件的操作可分为独占和并发。
打开linux内核源码,可以看到内核中对文件锁如下定义
struct file_lock {
struct file_lock *fl_next; /* singly linked list for this inode */
struct list_head fl_link; /* doubly linked list of all locks */
struct list_head fl_block; /* circular list of blocked processes */
fl_owner_t fl_owner;
unsigned char fl_flags;
unsigned char fl_type;
unsigned int fl_pid;
struct pid *fl_nspid;
wait_queue_head_t fl_wait;
struct file *fl_file;
loff_t fl_start;
loff_t fl_end;
struct fasync_struct * fl_fasync; /* for lease break notifications */
unsigned long fl_break_time; /* for nonblocking lease breaks */
const struct file_lock_operations *fl_ops; /* Callbacks for filesystems */
const struct lock_manager_operations *fl_lmops; /* Callbacks for lockmanagers */
union {
struct nfs_lock_info nfs_fl;
struct nfs4_lock_info nfs4_fl;
struct {
struct list_head link; /* link in AFS vnode's pending_locks list */
int state; /* state of grant or error if -ve */
} afs;
} fl_u;
};
在Linux中有强制锁和建议锁两种锁,强制锁由系统内核空间支持(和内核操作相关的函数都会判断),建议锁其实就是一个标识锁由用户空间支持(手动判断)。
可以使用 man fcntl来查看
int fcntl(int fildes, in cmd, struct flock *arg);
需要的头文件:
参数二cmd:
F_GETLK //得到锁
F_SETLK //设置锁
F_SETLKW //设置锁并等待返回
参数三:
struct flock {
...
short l_type; /* Type of lock: F_RDLCK(共享锁),
F_WRLCK(独占锁), F_UNLCK (删除锁)*/
short l_whence; /* How to interpret l_start:
SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* Starting offset for lock (起点)*/
off_t l_len; /* Number of bytes to lock(长度) */
pid_t l_pid; /* PID of process blocking our lock
(F_GETLK only)(拥有锁的进程ID号) */
...
};
#include
#include
#include
#include
#include
#include
int main(){
//open file
int fd = open("hello", O_RDWRIO_CREAT, 0666);
if(fd > 0){
//lock file
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
lock.l_pid = getpid();
int rd = fcntl(fd, F_SETLK, &lock);
printf("return value of lock:%d\n", rd);
while(1){
rd++;
}
}
return 0;
}
三、错误处理
系统级调用函数失败之后会设置外部变量error的值来指明失败原因。然后可以使用perror将最新的error输出。#include
#include
#include
#include
int main(){
int fd = open("helloworld", O_RDONL, 0666);
if(fd < 0){
perror("open error");
}
return 0;
}