.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 != 0) exit(0);
setsid();
pid = fork();
if (pid != 0) exit(0);
umask(0);
// 这儿已经进入“守护进程”工作状态了!
// 关闭所有打开的文件描述符
int max = open("/dev/null", 0);
for (var i = 0; i <= max; i++) { close(i); }
// 设置标记,防止重复运行进入
Environment.SetEnvironmentVariable(DaemonTag,"yes");
//为execp参数重组参数
var args1 = args == null ? new string[2] : new string[args.Length + 2];
args1[0] = "MyDaemon";
args1[1] = Path.Combine(Environment.CurrentDirectory, Thread.GetDomain().FriendlyName);
if (args1.Length > 2)
{
for (var i = 0; i < args.Length; i++)
{ args1[i + 2] = 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 = 0;
static void DaemonWorkFunct() {
fs = File.Open("/tmp/daemon.txt", FileMode.OpenOrCreate);
var t = new System.Timers.Timer() { Interval = 1000 };
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, 0, b.Length);
fs.Flush();
count++;
if (count > 100) {
fs.Close();
fs.Dispose();
exit(0);
}
}
[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打印了一行字符。
原文地址:http://www.cnblogs.com/yunei/p/6761218.html
.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注
.NET跨平台实践:再谈用C#开发Linux守护进程 — 完整篇相关推荐
- .NET跨平台实践:.NetCore、.Net5/6 Linux守护进程设计
几年前,我写过两篇关于用C#开发Linux守护进程的技术文章,分别是<.NET跨平台实践:用C#开发Linux守护进程.NET跨平台实践:再谈用C#开发Linux守护进程 - 完整篇 这就是本文 ...
- C# Net6开发Linux守护进程(后台服务程序,类似Windows服务)案例
C# Net6开发Linux守护进程(后台服务程序,类似Windows服务)案例 背景 C# net6开发Linux守护进程要点 背景 在使用net6开发Linux程序时,除了AspNet Core项 ...
- .NET跨平台实践:用C#开发Linux守护进程
Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon也能在后台正常工作. 一句话,为L ...
- Linux多进程开发(三)进程创建之守护进程的学习
之前发过一篇守护进程的文章,但是解析的不够详细,这次,详细来解释守护进程的一些概念和特性. 概念: 后台运行.没有控制端与之相连的进程.独立于控制终端,通常周期性的执行某种任务. Wh ...
- python全栈开发-再谈编码 python_day_6
一. 回顾上周所有内容 一. python基础 Python是一门解释型. 弱类型语言 print("内容", "内容", end="\n" ...
- 再谈 Go 语言在前端的应用前景
12 月 23 日,七牛云 CEO & ECUG 社区发起人许式伟先生在 ECUG Con 2018 现场为大家带来了主题为<再谈 Go 语言在前端的应用前景>的内容分享. 本文是 ...
- “云计算”三部曲之二:与“云”共舞——再谈云计算
引言:去年,我曾在一篇名为<未来计算在"云-端">的文章中指出,纯"云计算"并不是启动计算未来的"万能钥匙","云+端 ...
- tensorflow和python先学哪个-前辈说先学会了这些Python知识点,再谈学习人工智能!...
原标题:前辈说先学会了这些Python知识点,再谈学习人工智能! 首先我们看一看Python的优势: 开源,跨平台. 社区.不要小看这一点.社区意味着有很多教程.书籍,出了问题很容易google到,乃 ...
- 再谈编程范式-程序语言背后的思想
link link 编程范式 托马斯.库尔提出"科学的革命"的范式论后,Robert Floyd在1979年图灵奖的颁奖演说中使用了编程范式一词.编程范式一般包括三个方面,以OOP ...
最新文章
- 浙大版《C语言程序设计(第3版)》题目集 练习2-17 生成3的乘方表 (15 分)
- 查看系统信息命令:uname
- 500 行代码写一个俄罗斯方块游戏
- 查看系统各个进程打开的文件描述符数量
- android adb install Failure,提示base.apkcode is missing问题的解决
- python链表的创建_python数据结构之链表的实例讲解
- 第九节:委托和事件(1)(委托的发展历史、插件式编程、多播委托)
- 高斯核函数python代码_单类SVM:SVDD
- 【转载翻译】Debian配置Networking 和 apt-get 源信息 开启root远程登录权限
- Day 5内存管理,定义变量
- case when的使用方法
- 使用Arduino开发板和颜色传感器区分不同颜色
- Http响应Response详解
- Java面向对象三大特征---继承
- 如何用java取对数_使用Java中的Math.log获取自然对数值
- kingbase之时间日期加减
- Hello Kitty
- 操作系统---页式地址重定位
- 一个类似JQuery的精简版框架
- Python+Vue计算机毕业设计高考填报志愿综合参考系统1kc8i(源码+程序+LW+部署)