文件锁
来源:互联网 发布:罪恶装备人物乐乎 编辑:程序博客网 时间:2024/05/21 09:58
利用mktemp和fcntl实现进程间互斥操作
struct flock lock_it, unlock_it;
int lock_fd = -1;
void my_lock_init(char *pathname)
{
char lock_file[64];
strncpy(lock_file, pathname, sizeof(lock_file));
lock_file[sizeof(lock_file) - 1] = '/0';
if (mktemp(lock_file) == NULL) {
perror("mktemp");
exit(-1);
}
if ((lock_fd = open(lock_file, O_CREAT | O_WRONLY, 0600)) < 0) {
perror("open lock file");
exit(-1);
}
unlink(lock_file); /* unlink 不影响文件打开状态,也省却了某些
* 好事者看见锁文件就妄图删除之为快 */
lock_it.l_type = F_WRLCK;
lock_it.l_whence = SEEK_SET;
lock_it.l_start = 0;
lock_it.l_len = 0;
unlock_it.l_type = F_UNLCK;
unlock_it.l_whence = SEEK_SET;
unlock_it.l_start = 0;
unlock_it.l_len = 0;
}
void my_lock( )
{
while (fcntl(lock_fd, F_SETLKW, &lock_it) < 0) {
if (errno == EINTR)
continue;
else {
perror("fcntl lock");
exit(-1);
}
}
}
void my_unlock( )
{
if (fcntl(lock_fd, F_SETLKW, &unlock_it) < 0) {
perror("fcntl lock");
exit(-1);
}
}
文件描述符和文件流之间的转换
FILE *fdopen(int fildes, const char *type);
这个函数很有用的,功能是将一个流关联到一个打开的文件号filedes上,该filedes可以是open、pipe、dup、dup2和creat等调用返回的结果。type指定流打开方式,同fopen的打开方式,如"a","r","w"等等,fdopen的流打开方式服从filedes的打开方式,比如filedes的open指定O_RDONLY,那么fdopen也只能指定"r"的打开方式了。
用fdopen的好处很明显,如果你不得已只能打开文件号,比如socket或者dup调用,但又想用fprintf,fscanf等流操作来进行读写,那么就再fdopen一次好了。
int fileno(FILE stream);
用fileno有什么好处呢?你用fopen打开了文件,但是又想用flock或者lockf来给文件加锁,或者用fcntl来进行某些底层的操作,但上述这些函数只能对打开的文件号操作,而不能对打开流,这时候就用fileno再flock、lockf、fcntl好了。
如何避免产生zombie process
通常一个子进程终止后,需要父进程对其进行善后工作(获取子进程的结束状态,释放它仍占用的资源等等),wait系统调用就是干这件事。在子进程结束后,父进程还没有对它善后之前这段时间,这个子进程就是zombieprocess(僵死进程)。如果父进程无法wait子进程,怎样才能避免zombie呢?有两种办法:
- 捕获SIGCHLD信号。子进程正常或异常结束时,内核就会向其父进程发送SIGCHLD信号。所以我们可以这样设置这个信号的处理函数:
static void sigchld(int sig)
{
int rv;
do
rv = waitpid(0, NULL, WNOHANG);
while (rv > 0);
}
- 连续fork两次。子进程直接退出,孙子进程被init进程接管,所以就不用担心它会成为zombie了。
如何成为daemon进程
下面是从《Unix高级环境编程》摘过来的代码(Page 314):
static int daemon_init()
{
pid_t pid;
if((pid = fork()) <0)
return -1;
else if(pid !=0 )
exit(0); /* parent goes bye-bye */
/* child continues */
setsid(); /* become session leader */
chdir("/"); /* change working directory */
umask(0); /* clear our file mode creation mask */
return 0;
}
如何使一个程序同时只能运行一个进程实例
利用PID文件和文件锁实现。PID文件就是一个保存了进程pid的文件。
#define PIDFILE "/tmp/proc.pid"
static int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
{
struct flock lock;
lock.l_type = type;
lock.l_start = offset;
lock.l_whence = whence;
lock.l_len = len;
return (fcntl(fd,cmd, &lock));
}
#define write_lock(fd, offset, whence, len) lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len)
static void check_single_on()
{
int fd, val;
char buf[10];
if((fd = open(PIDFILE, O_WRONLY | O_CREAT, 0644)) <0 ) {
perror("open in check_single_on()");
exit(1);
}
/* try and set a write lock on the entire file */
if(write_lock(fd, 0, SEEK_SET, 0) <0 ) {
if(errno == EACCES || errno == EAGAIN) {
printf("daemon is already running./n");
exit(0); /* gracefully exit, daemon is already running */
}else {
perror("write_lock");
close(fd);
exit(1);
}
}
/* truncate to zero length, now that we have the lock */
if(ftruncate(fd, 0) <0) {
perror("ftruncate");
close(fd);
exit(1);
}
/* write our process id */
sprintf(buf, "%d/n", getpid());
if(write(fd, buf, strlen(buf)) != strlen(buf)) {
perror("write in check_single_on()");
close(fd);
exit(1);
}
/* set close-on-exec flag for descriptor */
if((val = fcntl(fd, F_GETFD, 0) <0 )) {
perror("fcntl");
close(fd);
exit(1);
}
val |= FD_CLOEXEC;
if(fcntl(fd, F_SETFD, val) <0 ) {
perror("fcntl again");
close(fd);
exit(1);
}
/* leave file open until we terminate: lock will be held */
}
检测一个进程是否正在运行:
static int check_proc_running()
{
int fd, rv;
char buf[10];
if((fd = open(PIDFILE, O_RDWR | O_CREAT, 0644)) <0 ) {
perror("open in check_proc_running()");
exit(1);
}
/* try and set a write lock on the entire file */
if(write_lock(fd, 0, SEEK_SET, 0) <0 ) {
if(errno == EACCES || errno == EAGAIN) {
bzero(buf, 10);
rv = read(fd, buf, 10);
buf[rv] = '/0';
close(fd);
return atoi(buf);
}else {
perror("write_lock");
close(fd);
return -1;
}
}
close(fd);
printf("daemon is not running now./n");
return -1;
}
- 文件操作-文件锁
- Linux文件---文件锁
- 文件锁
- 文件锁
- 文件锁
- 文件锁
- 文件锁
- 文件锁
- 文件锁
- 文件锁
- 文件锁
- 文件锁
- 文件锁
- 文件锁
- 文件锁
- 文件锁
- 文件锁
- 文件锁
- SQL语句 SELECT LIKE 用法详解
- Nhibernate 之 二级缓存
- 获取IP
- android 包
- php soap 详解 附简单案例
- 文件锁
- oracle expdp/impdp用法简要介绍
- 复杂报表解决方案之比较
- Windows CE下的字符串
- Agile Managers Build Trusting Relationships with Their Teams
- 正则表达式30分钟入门教程
- windows 2003服务器优化设置
- 漫谈数据库索引
- 何你的简历石沉大海———业内人士惊暴网络求职黑幕!!