.NET跨平台实践:再谈用C#开发Linux守护进程 — 完整篇
Linux守护进程是Linux的后台服务进程,相当于Windows服务,对于为Linux开发服务程序的朋友来说,Linux守护进程相关技术是必不可少的,因为这个技术不仅仅是为了开发守护进程,还可以拓展到多进程,父子进程文件描述符共享,父子进程通讯、控制等方面,是实现Linux大型服务的基础技术之一。
去年我也曾写了一篇关于守护进程的帖子,名字叫《.NET跨平台实践:用C#开发Linux守护进程》,这篇文章的的确确实现了一个Daemon,不过,它有一个弱点,不能运行多线程!
这篇帖子的目的就是进一步完善,让我们写出一个功能完整,可以用于生产环节的基本的守护进程。
先帖代码(假设项目名是daemon):
- using System;
- using System.Threading;
- using System.Timers;
- using System.Runtime.InteropServices;
- using System.IO;
- using System.Text;
- /********************************************
- * 一个完整的linux daemon示例,作者宇内流云 *
- ********************************************/
- namespace daemon
- {
- class Program
- {
- const string DaemonTag = "--daemon.";
- static void Main(string[] args)
- {
- // 判断是否已经进入Daemon状态,如果是,就直接执行后台主函数
- if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable(DaemonTag)) == false)
- {
- Environment.SetEnvironmentVariable(DaemonTag, null);
- DaemonMain(args);
- return;
- }
- // 如果还没有进入daemon状态,就作daemon处理
- /////////////////////////////////////////////////////
- int pid = fork();
- if (pid != ) exit();
- setsid();
- pid = fork();
- if (pid != ) exit();
- umask();
- // 这儿已经进入“守护进程”工作状态了!
- // 关闭所有打开的文件描述符
- int max = open("/dev/null", );
- for (var i = ; i <= max; i++) { close(i); }
- // 设置标记,防止重复运行进入
- Environment.SetEnvironmentVariable(DaemonTag,"yes");
- //为execp参数重组参数
- var args1 = args == null ? new string[] : new string[args.Length + ];
- args1[] = "MyDaemon";
- args1[] = Path.Combine(Environment.CurrentDirectory, Thread.GetDomain().FriendlyName);
- if (args1.Length > )
- {
- for (var i = ; i < args.Length; i++)
- { args1[i + ] = args[i]; }
- }
- //守护状态下重新加载和运行本程序
- execvp("mono", args1);
- }
- /// <summary>
- /// Daemon工作状态的主方法
- /// </summary>
- /// <param name="aargs"></param>
- static void DaemonMain(string[] aargs)
- {
- //启动一个线程去处理一些事情
- (new Thread(DaemonWorkFunct) { IsBackground = true }).Start();
- //daemon时,控制台输入、输出流已经关闭
- //请不要再用Console.Write/Read等方法
- //阻止daemon进程退出
- (new AutoResetEvent(false)).WaitOne();
- }
- static FileStream fs;
- static int count = ;
- static void DaemonWorkFunct() {
- fs = File.Open("/tmp/daemon.txt", FileMode.OpenOrCreate);
- var t = new System.Timers.Timer() { Interval = };
- t.Elapsed += OnElapsed;
- t.Start();
- }
- private static void OnElapsed(object sender, ElapsedEventArgs e)
- {
- var s = DateTime.Now.ToString("yyy-MM-dd HH:mm:ss") + "\n";
- var b = Encoding.ASCII.GetBytes(s);
- fs.Write(b, , b.Length);
- fs.Flush();
- count++;
- if (count > ) {
- fs.Close();
- fs.Dispose();
- exit();
- }
- }
- [DllImport("libc", SetLastError = true)]
- static extern int fork();
- [DllImport("libc", SetLastError = true)]
- static extern int setsid();
- [DllImport("libc", SetLastError = true)]
- static extern int umask(int mask);
- [DllImport("libc", SetLastError = true)]
- static extern int open([MarshalAs(UnmanagedType.LPStr)]string pathname, int flags);
- [DllImport("libc", SetLastError = true)]
- static extern int close(int fd);
- [DllImport("libc", SetLastError = true)]
- static extern int exit(int code);
- [DllImport("libc", SetLastError = true)]
- static extern int execvp([MarshalAs(UnmanagedType.LPStr)]string file, string[] argv);
- }
- }
以上代码的工作过程是:判断程序自身是否已经处于daemon(后台服务)状态,如果是,就直接开始具体的服务工作(开启一个线程,每秒向 /tmp/daemon.txt中打印一行字符,100次后退出),如果不是daemon状态,就进入Daemon处理,使之进入daemon工作状态。
以上代码编译后,会生成一个叫 daemon.exe 的程序,当然,这个程序是为linux开发的,不能在windows上运行。现在,我把它放到linux上面,用mono daemon.exe命令启动它。
这时我们可以看到这个程序启动后,控制台上没有任何输出,也没有阻塞控制台,那么,在哪儿能找到它呢?用 ps -ef命令看看,原来它真的已经在后台运行起来了。
再看看这个后台进程是否完成了它的工作:cat /tmp/daemon.txt 查看文件内容:
从生成的文件内容看,这个Daemon服务程序的确按我们的设计意图,每秒钟向/tmp/daemon.txt打印了一行字符。
注:本文为 宇内流云 (邮箱:j66x@163.com)原创作品,c#开发Linux守护进程的完整技术亦属首发,如需转载,请注明出处和作者。
.NET跨平台实践:再谈用C#开发Linux守护进程 — 完整篇的更多相关文章
- .NET跨平台实践:再谈用C#开发Linux守护进程
Linux守护进程是Linux的后台服务进程,相当于Windows服务进程,对于为Linux开发服务程序的朋友来说,Linux守护进程相关技术是必不可少的,因为这个技术不仅仅是开发守护进程,还可以拓展 ...
- .NET跨平台实践:.NetCore、.Net5/6 Linux守护进程设计
之前,我写过两篇关于用C#开发Linux守护进程的技术文章,分别是<.NET跨平台实践:用C#开发Linux守护进程>和<.NET跨平台实践:再谈用C#开发Linux守护进程 - 完 ...
- C#开发Linux守护进程
用C#开发Linux守护进程 Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon ...
- .NET跨平台实践:用C#开发Linux守护进程
Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon也能在后台正常工作. 一句话,为L ...
- .NET跨平台实践:用C#开发Linux守护进程(转)
Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon也能在后台正常工作. 一句话,为L ...
- .NET跨平台实践:用C#开发Linux守护进程-Daemon
Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon也能在后台正常工作. 一句话,为L ...
- linux守护进程编写实践
主要参考:http://colding.bokee.com/5277082.html (实例程序是参考这的) http://wbwk2005.blog.51cto.com/2215231/400260 ...
- 巨蟒python全栈开发linux之centos6 第二篇
1. .nginx负载均衡的实现 .准备三台机器,准备3台虚拟机,或者和俩同桌交流一下 192.168.226.128 是nginx资源服务器,返回页面的 192.168.226.129 用作ngin ...
- Linux C++ 开发简介(包括Linux守护线程)
阅读目录 简介 操作系统 编辑器 编译器 构建系统 调试 IDE 可执行程序.动态库.静态库 服务 Windows服务简介 创建Windows服务 注册Windows服务 管理Windows服务 Li ...
随机推荐
- Win7 VS2015环境编译Libpng
第3次编译Libpng依然想不起任何东西,为了不浪费第4次的时间... http://libpng.com/pub/png/libpng.html http://www.zlib.net/ 解压两个压 ...
- 使用spring boot +WebSocket实现(后台主动)消息推送
言:使用此webscoket务必确保生产环境能兼容/支持!使用此webscoket务必确保生产环境能兼容/支持!使用此webscoket务必确保生产环境能兼容/支持!主要是tomcat的兼容与支持. ...
- PageInfo 前台分页js,带分页栏
在使用mybatis3,并且使用分页,PageHelper 接口,分页还是很好使用的.使用pageInfo的后台分页接口. /** * * @param switchPage方法,切换页码方法 * * ...
- Jersey RESTful WebService框架学习(二)使用@PathParam
@PathParamuri路径参数写在方法的参数中,获得请求路径参数.比如:@PathParam("username") String userName 前端请求: <!DO ...
- session(会话)研究(一)基础
一.Session对象的生成 session对象生成的过程,可以通过一个直观图进行观察. 也就是说,客户第一次请求访问时,Cookie中是没有SessionID的.在第一次访问之后,由服务器生成一个S ...
- Ubuntu Remove Mysql.service in Systemctl
After installing MySQL 5.7, I do not want to start MySQL via systemctl. It's unconvenient and compli ...
- MySQL查询实例
单表查询查询所有列 1 SELECT * FROM product; 查询指定列 1 SELECT pro_name,price,pinpai FROM product; 添加常量列 1 SELECT ...
- 【python-字典】判断python字典中key是否存在的
一般有两种通用做法: 第一种方法:使用自带函数实现: 在python的字典的属性方法里面有一个has_key()方法: #生成一个字典 d = {'name':Tom, 'age':10, 'Tel' ...
- HDU3488 Tour
Tour Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others) Total Submi ...
- Python3 安装 PyQt5 -pycharm 环境搭建
执行命令: pip3 install PyQt5 PyQt5+python3+pycharm开发环境配置 1.下载PyQt 官方网站:http://www.riverbankcomputing.c ...