文件操作的学习
ifdown eth0
ifup eth0
ps -ef | grep 进程名
比如 gcc main.c - o main,这个变成生成的可执行文件main就是进程名
第二卷是系统调用
第三卷是库调用
//file1 size
ret = lseek(file1,0,SEEK_END);
直接IO 绕过缓存,不会出现write成功数据丢失的情况,血案不再重演.
注意:直接I/O的缺点就是如果访问的数据不在应用程序缓存中, 那么每次数据都会直接从磁盘进行加载,这种直接加载会非常缓慢! 通常直接I/O跟异步I/O结合使用会得到较好的性能。
O_DIRECT是:跳过高速页缓存,直接存到物理磁盘 缺点:每次从磁盘中加载非常慢
O_SYNC是:不跳过高速页缓存,到了高速页缓存后,马不停蹄的存到物理磁盘,才返回写入成功. 缺点:这种数据有保证,但是效率并不高
以上两个都不写:不跳过高速页缓存,到了高速页缓存后,此时返回写入成功并在高速页缓存停留一会之后,才存入到物理磁盘.(如果在停留的这会时间段内,服务器宕机,数据就会丢失无法找回)
缓存同步可以保证我们想啥时候把数据从高速页缓存同步到磁盘,就啥时候把数据从高速页缓存同步到磁盘,完全有我们自己来确定同步到磁盘的时机!
- sync - 将所有修改过的块缓冲区排入写队列,然后就返回,它并不等待实际写磁盘操作结束。(并不能保证数据有效,不是我们想要的!!!)
- fsync - 将fd对应文件的块缓冲区立即写入磁盘,并等待实际写磁盘操作结束返回。(很明显,这个才是我们想要的)
- fdatasync - 类似fsync,但只影响文件的数据部分(也就是说它只同步文件内容)。而除数据外,fsync 还会同步更新文件属性。
-
并发对文件I/O操作的影响
解决办法?使用文件锁fcntl函数
-
文件锁
-
用法:man 2 fcntl
-
头文件:
#include <unistd.h>
#include <fcntl.h>
-
函数定义:int fcntl(int fd, int cmd, ... /* arg */ );
- 参数: cmd 取值 F_GETLK, F_SETLK 和 F_SETLKW ,分别表示获取锁、设置锁和同步设置锁.
F_SETLK是如果没锁就设置锁,有锁也不等,直接函数调用(即不阻塞)
F_SETLKW是如果没锁就设置锁,有锁就一直等到对方解锁,然后再上锁(即阻塞)
-
文件锁的表示
1)struct flock
// struct flock 结构体说明
struct flock {
short l_type; /*F_RDLCK, F_WRLCK, or F_UNLCK */
off_t l_start; /*offset in bytes, relative to l_whence */
short l_whence; /*SEEK_SET, SEEK_CUR, or SEEK_END */ //分别表示开头,当前,结尾
off_t l_len; /*length, in bytes; 0 means lock to EOF */
pid_t l_pid; /*returned with F_GETLK */
};
l_type: 第一个成员是加锁的类型:只读锁,读写锁,或是解锁。
l_start和l_whence: 用来指明加锁部分的开始位置。
l_len: 是加锁的长度。
l_pid: 是加锁进程的进程id。
2)举例:
我们现在需要把一个文件的前三个字节加读锁,则该结构体的l_type=F_RDLCK, l_start=0, l_whence=SEEK_SET, l_len=3, l_pid不需要指定,然后调用fcntl函数时, cmd参数使F_SETLK.
//
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "test.txt" //要操作的文件名
int flock_set(int fd, int type)
{
printf("pid=%d into...\n", getpid());//通过getpid()获取当前进程号
struct flock flock;//这个结构体已在#include <fcntl.h>中定义,直接用就可以
fcntl(fd, F_GETLK, &flock);//先通过F_GETLK获取锁的状态
if (flock.l_type != F_UNLCK) {
if (flock.l_type == F_RDLCK) {
printf("flock has been set to read lock by %d\n", flock.l_pid);
} else if (flock.l_type == F_WRLCK) {
printf("flock has been set to write lock by %d\n", flock.l_pid);
}
}
flock.l_type = type;
flock.l_whence = SEEK_SET;//从文件开头上锁
flock.l_start = 0;//偏移0个字节
flock.l_len = 0;//0 means lock to EOF,即:0表示上锁的部分一直持续到文件尾部
flock.l_pid = -1;
if (fcntl(fd, F_SETLKW, &flock) < 0) {//设置阻塞同步锁,锁的类型已经包含在flock.l_type中
printf("set lock failed!\n");
return -1;
}
switch (flock.l_type) {//查看锁的类型
case F_RDLCK:
printf("read lock is set by %d\n", getpid());//读,也叫共享锁
break;
case F_WRLCK:
printf("write lock is set by %d\n", getpid());//写,也叫排他锁;(读读都可上锁;先读后写,写锁不能上;先写后读,读锁不能上;写写,第二个写锁不能上)
break;
case F_UNLCK:
printf("lock is released by %d\n", getpid());//释放
break;
default:
break;
}
printf("pid=%d out.\n", getpid());
return 0;
}
int main(void)
{
int fd;
fd = open(FILE_NAME, O_RDWR|O_CREAT, 0666);//可读可写,没有就创建
if (fd < 0) {
printf("open file %s failed!\n", FILE_NAME);
}
//flock_set(fd, F_WRLCK);//设置写锁
flock_set(fd, F_RDLCK);//设置读锁
getchar();
flock_set(fd, F_UNLCK);//释放锁
getchar();
close(fd);
return 0;
}