Linux Daemon & 单例模式 设计与实现
来源:互联网 发布:程序员 判刑 编辑:程序博客网 时间:2024/06/05 20:04
#PS:要转载请注明出处,本人版权所有
#PS:这个只是 《 我自己 》理解,如果和你的
#原则相冲突,请谅解,勿喷
单例模式
原理
创建一个保存进程名的文件,利用linux的文件锁来判断文件是否加锁来判断是否已有相同的程序运行。
例子
int CheckIsSingleton(int *fd){ struct flock loglock; char nowpid[10]; int num; if (0 > (*fd = open(LOCK_FILE_NAME, O_WRONLY | O_CREAT, 0600))) { perror("open lock file failed!"); return -1; } /*struct flock { ... short l_type; // Type of lock: F_RDLCK, //F_WRLCK, F_UNLCK short l_whence; // How to interpret l_start: //SEEK_SET, SEEK_CUR, SEEK_END off_t l_start; // Starting offset for lock off_t l_len; // Number of bytes to lock pid_t l_pid; // PID of process blocking our lock // (set by F_GETLK and F_OFD_GETLK) ... }; As well as being removed by an explicit F_UNLCK, record locks are auto‐ matically released when the process terminates.*/ memset(&loglock, 0, sizeof(struct flock)); loglock.l_type = F_WRLCK; loglock.l_whence = SEEK_SET; if ( 0 > fcntl(*fd, F_GETLK, &loglock) ){//检查是否能够加F_WRLCK锁,不能够确认文件是否有锁。 close(*fd); perror("fcntl F_WRLCK failed"); _exit(-1); } else{ if ( loglock.l_type != F_UNLCK){ close(*fd); write(2,"check F_WRLCK failed\n",sizeof("check F_WRLCK failed\n"));//stdout was closed!!! write(2,"The same process is running\n",sizeof("The same process is running\n")); _exit(-1); } } loglock.l_type = F_WRLCK; loglock.l_start = 0; //从文件开始加锁 loglock.l_whence = SEEK_SET; loglock.l_len = 0; //加锁整个文件 if ( 0 > fcntl(*fd, F_SETLK, &loglock) ){ close(*fd); perror("fcntl F_WRLCK failed"); printf("The same process is running\n"); _exit(-1); } num = sprintf(nowpid, "%d",getpid()); write(*fd, nowpid, num); return 0;}
Daemon 简单设计
原理
1 利用fork来实现。setsid使当前子进程成为新的进程组长,在使用fork使其与终端脱离,设置工作目录,设置文件掩码
2 利用系统提供的daemon()(此调用来至于glibc)来完成功能。(底层使用fork来实现)
例子
void CreateDaemonProcess_daemon()//根据daemon函数的源码来看,后面补充了一个fork比较安全{ /* The daemon() function is for programs wishing to detach themselves from the controlling terminal and run in the background as system daemons. If nochdir is zero, daemon() changes the process's current working directory to the root directory ("/"); otherwise, the current working directory is left unchanged. If noclose is zero, daemon() redirects standard input, standard output and standard error to /dev/null; otherwise, no changes are made to these file descriptors.intdaemon(nochdir, noclose) int nochdir, noclose;{ int fd; switch (__fork()) { case -1: return (-1); case 0: break; default: _exit(0); } if (__setsid() == -1) return (-1); if (!nochdir) (void)__chdir("/"); if (!noclose) { struct stat64 st; if ((fd = open_not_cancel(_PATH_DEVNULL, O_RDWR, 0)) != -1 && (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) == 0)) { if (__builtin_expect (S_ISCHR (st.st_mode), 1) != 0#if defined DEV_NULL_MAJOR && defined DEV_NULL_MINOR && (st.st_rdev == makedev (DEV_NULL_MAJOR, DEV_NULL_MINOR))#endif ) { (void)__dup2(fd, STDIN_FILENO); (void)__dup2(fd, STDOUT_FILENO); (void)__dup2(fd, STDERR_FILENO); if (fd > 2) (void)__close (fd); } else { // We must set an errno value since no // function call actually failed. close_not_cancel_no_status (fd); __set_errno (ENODEV); return -1; } } else { close_not_cancel_no_status (fd); return -1; } } return (0);}*/ if (0 > daemon(0, 0)) { perror("daemon call failed!"); _exit(-1); } //setsid(); // int fd; // if ( 0 > (fd = open("/dev/tty", O_RDWR )) ){ // perror("open tty failed!"); // _exit(-1); // } // if ( ioctl(fd, TIOCNOTTY, NULL) < 0){ // perror("ioctl TIOCNOTTY failed!"); // close(fd); // _exit(-1); // } // close(fd); int pid; pid = fork(); if (pid == -1) { perror("fork first error!"); } else if (pid > 0) { //parent 1 _exit(1); } else { //child pid==0 } return;}void CreateDaemonProcess_Fork(){ pid_t pid, pid1, pid2; pid = fork(); if (pid == -1) { perror("fork first error!"); } else if (pid > 0) { //parent 1 _exit(1); } else { //child pid==0 if (0 > (pid1 = setsid())) { perror("setsid() call failed!"); _exit(-1); // } else { printf("New session id is %d\n", pid1); } pid2 = fork(); if (pid2 == -1) { perror("fork second error!"); } else if (pid2 > 0) { //parent _exit(1); } else { chdir("/"); //change current working directory umask(0); return; } }}
说明:
1 双fork的原因是进程组长会开启终端。而我们的daemon程序是不需要终端的。
2 文件掩码用于设置默认的文件权限。
3 子进程会继承父进程的大部分属性,包括已打开文件描述符、文件掩码、工作目录等待,这些根据需求处理。
#PS:请尊重原创,不喜勿喷
#PS:要转载请注明出处,本人版权所有.
有问题请留言,看到后我会第一时间回复
阅读全文
0 0
- Linux Daemon & 单例模式 设计与实现
- 单例模式的设计与实现,及性能测试
- Java 设计模式之单例实现与分析
- 设计模式----C++实现单例模式
- 设计模式--单例模式 C++实现
- 设计模式C++实现--单例模式
- 设计模式--单例模式(C++实现)
- 设计模式--单例模式-Java实现
- 设计模式--单例模式python实现
- 设计模式:单例模式- 饿汉式实现
- 设计模式--单例模式--Java实现
- 设计模式-单例模式 C++实现
- 设计模式-Java实现单例模式
- JDK与设计模式:单例模式
- static与设计模式:单例模式
- Python与设计模式--单例模式
- 单例设计模式C++实现
- 单例设计模式的实现代码
- Linux用户与用户组详解
- 浅谈ARP欺骗
- Maven(二)eclipse创建maven项目
- Retrofit+RxJava学习笔记(1)
- 数据库事务隔离级别-- 脏读、幻读、不可重复读
- Linux Daemon & 单例模式 设计与实现
- 产品PRD文档撰写指南
- clisp 记录:6. 循环
- sem_init sem_post sem_destroy信号量介绍
- ios文件夹共享Files
- 计算机组成原理实验四:时序系统
- 生信宝典Linux学习系列文章整理
- 上传文件(lrzsz)
- elementUi的使用