同步——记录锁
2013-05-07 18:48
141 查看
记录锁是读写锁的一种扩展类型,它可用于有亲缘关系或无亲缘关系的进程之间共享某个文件的读与写。被锁住的文件通过其描述符访问,执行上锁操作的函数为fcntl。该种类型的锁通常在内核中维护,其属主是由属主的进程ID标识,可用于不同进程间的上锁。
Posix记录锁定义了一个特殊的字节范围以指定整个文件,它的起始偏移为0,长度也为0;粒度用于标记能被锁住的对象的大小,对于Posix记录锁来说,粒度就是1byte。#include <fcntl.h>
struct flock{
short l_type; /* F_RDLCK, F_WRLCK, F_UNLCK */
short l_whence; /* SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start;
off_t l_end; /* #bytes, 0 means until e-o-f */
pid_t l_pid; /* PID returned by F_GETLK */
};
int fcntl(int fd, int cmd, .../*struct flock *arg */); // 成功返回值取决于cmd,出错-1
cmd参数共有三个值:F_SETLK, F_GETLK, F_SETLKW(wait)
F_SETLK: 获取type或释放锁
F_SETLKW:与F_SETLK类似,会阻塞到该锁能够授权为止
F_GETLK:检查由arg指向的锁以确定是否有某个已存在的锁会妨碍将新锁授予调用进程。若不存在,由arg指向的flock结构的type成员就被置为F_UNLCK;否则返回已存在锁的信息,其中包括持有锁的进程ID
调用进程已持有的针对同一字节范围的锁不会妨碍它获取新锁,同一进程内后执行的获取锁命令覆盖先执行的命令。
fcntl记录上锁既可用于读也可用于写,对于一个文件的任意字节,最多只能存在一种类型的锁。而且,一个给定字节可以有多个读出锁,但只能有一个写入锁。自然,当一个描述符不是打开来读时,对它请求一个读出锁,错误发生;同样当一个描述符不是打开来写时,请求写入锁也会发生错误。对于一个打开着某个文件的给定进程来说,当它关闭该文件的所有描述符或它本身终止时,与该文件关联的所有锁都被删除。锁不能通过fork由子进程继承。
#include "unpipc.h"
void my_lock(int fd)
{
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0; /* write lock entire file */
Fcntl(fd, F_SETLKW, &lock);
}
void my_unlock(int fd)
{
struct flock lock;
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0; /* unlock entire file */
Fcntl(fd, F_SETLK, &lock);
}
Posix记录上锁称为劝告性上锁,内核维护着已有各个进程上锁的所有文件的正确信息,但是它不能防止拥有足够权限的其他进程乱来。Posix记录上锁对于协作进程足够了
记录上锁的一个常见用途是确保某个程序在任何时刻只有一个副本在运行,常用于守护进程
#include "unpipc.h"
#define PATH_PIDFILE "pidfile"
int
main(int argc, char **argv)
{
int pidfd;
char line[MAXLINE];
/* 4open the PID file, create if nonexistent */
pidfd = Open(PATH_PIDFILE, O_RDWR | O_CREAT, FILE_MODE);
/* 4try to write lock the entire file */
if (write_lock(pidfd, 0, SEEK_SET, 0) < 0) {
if (errno == EACCES || errno == EAGAIN)
err_quit("unable to lock %s, is %s already running?",
PATH_PIDFILE, argv[0]);
else
err_sys("unable to lock %s", PATH_PIDFILE);
}
/* 4write my PID, leave file open to hold the write lock */
snprintf(line, sizeof(line), "%ld\n", (long) getpid());
Ftruncate(pidfd, 0);
Write(pidfd, line, strlen(line));
/* then do whatever the daemon does ... */
pause();
}
Posix记录锁定义了一个特殊的字节范围以指定整个文件,它的起始偏移为0,长度也为0;粒度用于标记能被锁住的对象的大小,对于Posix记录锁来说,粒度就是1byte。#include <fcntl.h>
struct flock{
short l_type; /* F_RDLCK, F_WRLCK, F_UNLCK */
short l_whence; /* SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start;
off_t l_end; /* #bytes, 0 means until e-o-f */
pid_t l_pid; /* PID returned by F_GETLK */
};
int fcntl(int fd, int cmd, .../*struct flock *arg */); // 成功返回值取决于cmd,出错-1
cmd参数共有三个值:F_SETLK, F_GETLK, F_SETLKW(wait)
F_SETLK: 获取type或释放锁
F_SETLKW:与F_SETLK类似,会阻塞到该锁能够授权为止
F_GETLK:检查由arg指向的锁以确定是否有某个已存在的锁会妨碍将新锁授予调用进程。若不存在,由arg指向的flock结构的type成员就被置为F_UNLCK;否则返回已存在锁的信息,其中包括持有锁的进程ID
调用进程已持有的针对同一字节范围的锁不会妨碍它获取新锁,同一进程内后执行的获取锁命令覆盖先执行的命令。
fcntl记录上锁既可用于读也可用于写,对于一个文件的任意字节,最多只能存在一种类型的锁。而且,一个给定字节可以有多个读出锁,但只能有一个写入锁。自然,当一个描述符不是打开来读时,对它请求一个读出锁,错误发生;同样当一个描述符不是打开来写时,请求写入锁也会发生错误。对于一个打开着某个文件的给定进程来说,当它关闭该文件的所有描述符或它本身终止时,与该文件关联的所有锁都被删除。锁不能通过fork由子进程继承。
#include "unpipc.h"
void my_lock(int fd)
{
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0; /* write lock entire file */
Fcntl(fd, F_SETLKW, &lock);
}
void my_unlock(int fd)
{
struct flock lock;
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0; /* unlock entire file */
Fcntl(fd, F_SETLK, &lock);
}
Posix记录上锁称为劝告性上锁,内核维护着已有各个进程上锁的所有文件的正确信息,但是它不能防止拥有足够权限的其他进程乱来。Posix记录上锁对于协作进程足够了
记录上锁的一个常见用途是确保某个程序在任何时刻只有一个副本在运行,常用于守护进程
#include "unpipc.h"
#define PATH_PIDFILE "pidfile"
int
main(int argc, char **argv)
{
int pidfd;
char line[MAXLINE];
/* 4open the PID file, create if nonexistent */
pidfd = Open(PATH_PIDFILE, O_RDWR | O_CREAT, FILE_MODE);
/* 4try to write lock the entire file */
if (write_lock(pidfd, 0, SEEK_SET, 0) < 0) {
if (errno == EACCES || errno == EAGAIN)
err_quit("unable to lock %s, is %s already running?",
PATH_PIDFILE, argv[0]);
else
err_sys("unable to lock %s", PATH_PIDFILE);
}
/* 4write my PID, leave file open to hold the write lock */
snprintf(line, sizeof(line), "%ld\n", (long) getpid());
Ftruncate(pidfd, 0);
Write(pidfd, line, strlen(line));
/* then do whatever the daemon does ... */
pause();
}
相关文章推荐
- QQ聊天记录通过dropbox在不同mac机上同步
- 高速信号采集卡,250MSPS,最高支持128通道高速同步采集记录存储!
- 《影子跟随算法》目前试着自己写一个联网双人对战的小游戏 看到一篇网络同步的文章很受启发 这里记录一下
- 同步复制日常记录收集
- 电商中设置满包邮,满减等促销搞活动;电商平台同步到第三方,日志记录
- 使用rsync同步镜像服务器数据,安装记录
- spring4学习记录07-调用远程服务RPC(同步)
- 如何避免mysql 主从同步中由于数据记录找不到和主键重复错误导致的同步异常问题
- rsync同步工作记录20130916
- 利用rsync工具进行同步windows和linux机器之间的文件工作记录20130614
- 关于 OGG "Loading data from file to Replicat"同步含有lob字段表的部分记录的关键参数
- 工作中串口读写同步方式下的效率优化记录事件
- 小凡的Linux主机与时间服务器同步记录
- 记录editText中 的 字符串 同步 显示在 textview中的代码
- 使用dblink同步本地数据库新增记录到远程服务器
- Linux下的进程同步机制 – 记录锁
- C# DevExpress之GridView同步滚动条记录方法
- OPC工作记录整理——第六篇(同步读取和异步读取)
- Linux开启同步history记录到messages
- UE4同步记录