文件锁

利用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系统调用就是干这件事。在子进程结束后,父 进程还没有对它善后之前这段时间,这个子进程就是zombie process(僵死进程)。如果父进程无法wait子进程,怎样才能避免zombie呢?有两种办法:

  1. 捕获SIGCHLD信号。子进程正常或异常结束时,内核就会向其父进程发送SIGCHLD信号。所以我们可以这样设置这个信号的处理函数:
static
 void
 sigchld
(int
 sig
)
{
int rv ;
do
rv = waitpid(0, NULL, WNOHANG);
while (rv > 0);
}
  1. 连续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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux VFS(Virtual File System)文件是用于在多进程或多线程环境下对文件进行并发访问控制的机制。它可以确保同一时间只有一个进程或线程能够对文件进行写操作,从而避免数据的不一致性和竞争条件的发生。 Linux VFS文件主要有两种类型:共享(读)和独占(写)。共享允许多个进程或线程同时对文件进行读操作,而独占则只允许一个进程或线程对文件进行写操作。 在Linux中,文件是通过fcntl系统调用来实现的。具体而言,可以使用fcntl函数来获取、设置和释放文件。fcntl函数的相关参数包括文件描述符、类型、起始位置和长度等。 以下是一些关于Linux VFS文件的常见问题及回答: 1. 什么是共享和独占? 共享(读)允许多个进程或线程同时对文件进行读操作,不会阻塞其他进程或线程的读操作。独占(写)则只允许一个进程或线程对文件进行写操作,其他进程或线程的读写操作都会被阻塞。 2. 如何获取文件? 可以使用fcntl函数来获取文件。通过设置fcntl函数的参数,可以指定类型、起始位置和长度等信息。 3. 文件的作用是什么? 文件可以确保同一时间只有一个进程或线程能够对文件进行写操作,从而避免数据的不一致性和竞争条件的发生。它在多进程或多线程环境下起到了并发访问控制的作用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值