Chinaunix首页 | 论坛 | 博客
  • 博客访问: 532666
  • 博文数量: 150
  • 博客积分: 5010
  • 博客等级: 大校
  • 技术积分: 1861
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-17 00:19
文章分类

全部博文(150)

文章存档

2011年(1)

2009年(14)

2008年(135)

我的朋友

分类: LINUX

2008-11-13 11:54:50

建议性锁可由精灵进程使用以保证该精灵进程只有一个副本在运行。起动时,很多精灵进
程都把它们的进程I D写到一个各自专用的P I D文件上。系统停机时,可以从这些文件中取用这
些精灵进程的进程I D。防止一个精灵进程有多份副本同时运行的方法是:在精灵进程开始运行
时,在它的进程I D文件上设置一把写锁。如果在它运行时一直保持这把锁,则不可能再起动它
的其他副本。程序1 2 - 5实现了这一技术。
因为进程I D文件可能包含以前的精灵进程I D,而且其长度可能长于当前进程的I D,例如
该文件中以前的内容可能是1 2 3 4 5 \ n,而现在的进程I D是6 5 4,我们希望该文件现在只包含
6 5 4 \ n,而不是6 5 4 \ n 5 \ n,所以在写该文件时,先将其截短为0。注意,要在设置了锁之后再调
用截短文件长度的函数f t r u n c a t e。在调用o p e n时不能指定O _ T R U N C,因为这样做会在有一个
这种精灵进程运行并对该文件加锁时也会使该文件截短为0。(如果使用强制性锁而不是建议性
锁,则可使用O _ T R U N C。本节最后将讨论强制性锁。)
在本实例中,也对该描述符设置了运行时关闭标志。这是因为精灵进程常常f o r k并e x e c其
他进程,并无需在另一个进程中使该文件也处在打开状态。


#include    <sys/types.h>
#include    <sys/stat.h>
#include    <errno.h>
#include    <fcntl.h>
#include    "ourhdr.h"

#include    <errno.h>        /* for definition of errno */
#include    <stdarg.h>        /* ANSI C header file */
#include    "ourhdr.h"
#include <signal.h>

#include    <sys/types.h>    /* required for some of our prototypes */
#include    <stdio.h>        /* for convenience */
#include    <stdlib.h>        /* for convenience */
#include    <string.h>        /* for convenience */
#include    <unistd.h>        /* for convenience */
static void    err_doit(int, const char *, va_list);

#define    MAXLINE    4096            /* max line length */

#define    FILE_MODE    (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
                    /* default file access permissions for new files */
#define    DIR_MODE    (FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH)
                    /* default permissions for new directories */

//typedef    void    Sigfunc(int);    /* for signal handlers */


                    /* 4.3BSD Reno doesn't define SIG_ERR */
#if    defined(SIG_IGN) && !defined(SIG_ERR)
#define    SIG_ERR    ((Sigfunc *)-1)
#endif

#define    min(a,b)    ((a) < (b) ? (a) : (b))
#define    max(a,b)    ((a) > (b) ? (a) : (b))

                    /* prototypes for our own functions */
char    *path_alloc(int *);            /* {Prog pathalloc} */
int         open_max(void);            /* {Prog openmax} */
void     clr_fl(int, int);            /* {Prog setfl} */
void     set_fl(int, int);            /* {Prog setfl} */
void     pr_exit(int);                /* {Prog prexit} */
void     pr_mask(const char *);        /* {Prog prmask} */
Sigfunc    *signal_intr(int, Sigfunc *);/* {Prog signal_intr_function} */

int         tty_cbreak(int);            /* {Prog raw} */
int         tty_raw(int);                /* {Prog raw} */
int         tty_reset(int);            /* {Prog raw} */
void     tty_atexit(void);            /* {Prog raw} */
#ifdef    ECHO    /* only if has been included */
struct termios    *tty_termios(void);    /* {Prog raw} */
#endif

void     sleep_us(unsigned int);    /* {Ex sleepus} */
ssize_t     readn(int, void *, size_t);/* {Prog readn} */
ssize_t     writen(int, const void *, size_t);/* {Prog writen} */
int         daemon_init(void);            /* {Prog daemoninit} */

int         s_pipe(int *);                /* {Progs svr4_spipe bsd_spipe} */
int         recv_fd(int, ssize_t (*func)(int, const void *, size_t));
                                    /* {Progs recvfd_svr4 recvfd_43bsd} */
int         send_fd(int, int);            /* {Progs sendfd_svr4 sendfd_43bsd} */
int         send_err(int, int, const char *);/* {Prog senderr} */
int         serv_listen(const char *);    /* {Progs servlisten_svr4 servlisten_44bsd} */
int         serv_accept(int, uid_t *);    /* {Progs servaccept_svr4 servaccept_44bsd} */
int         cli_conn(const char *);    /* {Progs cliconn_svr4 cliconn_44bsd} */
int         buf_args(char *, int (*func)(int, char **));
                                    /* {Prog bufargs} */

int         ptym_open(char *);            /* {Progs ptyopen_svr4 ptyopen_44bsd} */
int         ptys_open(int, char *);    /* {Progs ptyopen_svr4 ptyopen_44bsd} */
#ifdef    TIOCGWINSZ
pid_t     pty_fork(int *, char *, const struct termios *,
                 const struct winsize *);    /* {Prog ptyfork} */
#endif
int
lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
{
    struct flock    lock;

    lock.l_type = type;        /* F_RDLCK, F_WRLCK, F_UNLCK */
    lock.l_start = offset;    /* byte offset, relative to l_whence */
    lock.l_whence = whence;    /* SEEK_SET, SEEK_CUR, SEEK_END */
    lock.l_len = len;        /* #bytes (0 means to EOF) */

    return( fcntl(fd, cmd, &lock) );
}

int        lock_reg(int, int, int, off_t, int, off_t);
                                    /* {Prog lockreg} */
#define    read_lock(fd, offset, whence, len) \
            lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, len)
#define    readw_lock(fd, offset, whence, len) \
            lock_reg(fd, F_SETLKW, F_RDLCK, offset, whence, len)
#define    write_lock(fd, offset, whence, len) \
            lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len)
#define    writew_lock(fd, offset, whence, len) \
            lock_reg(fd, F_SETLKW, F_WRLCK, offset, whence, len)
#define    un_lock(fd, offset, whence, len) \
            lock_reg(fd, F_SETLK, F_UNLCK, offset, whence, len)

pid_t    lock_test(int, int, off_t, int, off_t);
                                    /* {Prog locktest} */

#define    is_readlock(fd, offset, whence, len) \
            lock_test(fd, F_RDLCK, offset, whence, len)
#define    is_writelock(fd, offset, whence, len) \
            lock_test(fd, F_WRLCK, offset, whence, len)

void    err_dump(const char *, ...);    /* {App misc_source} */
void    err_msg(const char *, ...);
void    err_quit(const char *, ...);
void    err_ret(const char *, ...);
void    err_sys(const char *, ...);

void    log_msg(const char *, ...);        /* {App misc_source} */
void    log_open(const char *, int, int);
void    log_quit(const char *, ...);
void    log_ret(const char *, ...);
void    log_sys(const char *, ...);

void    TELL_WAIT(void);        /* parent/child from {Sec race_conditions} */
void    TELL_PARENT(pid_t);
void    TELL_CHILD(pid_t);
void    WAIT_PARENT(void);
void    WAIT_CHILD(void);

char    *pname = NULL;        /* caller can set this from argv[0] */

/* Nonfatal error related to a system call.
 * Print a message and return. */


void
err_ret(const char *fmt, ...)
{
    va_list        ap;

    va_start(ap, fmt);
    err_doit(1, fmt, ap);
    va_end(ap);
    return;
}

/* Fatal error related to a system call.
 * Print a message and terminate. */


void
err_sys(const char *fmt, ...)
{
    va_list        ap;

    va_start(ap, fmt);
    err_doit(1, fmt, ap);
    va_end(ap);
    exit(1);
}

/* Fatal error related to a system call.
 * Print a message, dump core, and terminate. */


void
err_dump(const char *fmt, ...)
{
    va_list        ap;

    va_start(ap, fmt);
    err_doit(1, fmt, ap);
    va_end(ap);
    abort();        /* dump core and terminate */
    exit(1);        /* shouldn't get here */
}

/* Nonfatal error unrelated to a system call.
 * Print a message and return. */


void
err_msg(const char *fmt, ...)
{
    va_list        ap;

    va_start(ap, fmt);
    err_doit(0, fmt, ap);
    va_end(ap);
    return;
}

/* Fatal error unrelated to a system call.
 * Print a message and terminate. */


void
err_quit(const char *fmt, ...)
{
    va_list        ap;

    va_start(ap, fmt);
    err_doit(0, fmt, ap);
    va_end(ap);
    exit(1);
}

/* Print a message and return to caller.
 * Caller specifies "errnoflag". */


static void
err_doit(int errnoflag, const char *fmt, va_list ap)
{
    int        errno_save;
    char    buf[MAXLINE];

    errno_save = errno;        /* value caller might want printed */
    vsprintf(buf, fmt, ap);
    if (errnoflag)
        sprintf(buf+strlen(buf), ": %s", strerror(errno_save));
    strcat(buf, "\n");
    fflush(stdout);        /* in case stdout and stderr are the same */
    fputs(buf, stderr);
    fflush(NULL);        /* flushes all stdio output streams */
    return;
}

#define    PIDFILE        "daemon.pid"

int
main(void)
{
    int        fd, val;
    char    buf[10];

    if ( (fd = open(PIDFILE, O_WRONLY | O_CREAT, FILE_MODE)) < 0)
        err_sys("open error");

            /* 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("the process is running");exit(0);}    /* gracefully exit, daemon is already running */
        else
            err_sys("write_lock error");
    }

            /* truncate to zero length, now that we have the lock */
    if (ftruncate(fd, 0) < 0)
        err_sys("ftruncate error");

            /* and write our process ID */
    sprintf(buf, "%d\n", getpid());
    if (write(fd, buf, strlen(buf)) != strlen(buf))
        err_sys("write error");

            /* set close-on-exec flag for descriptor */
    if ( (val = fcntl(fd, F_GETFD, 0)) < 0)
        err_sys("fcntl F_GETFD error");
    val |= FD_CLOEXEC;
    if (fcntl(fd, F_SETFD, val) < 0)
        err_sys("fcntl F_SETFD error");

    /* leave file open until we terminate: lock will be held */

    /* do whatever ... */
    while(1)
     pause();

    exit(0);
}


阅读(1257) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~