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守护进程 — 完整篇相关推荐

  1. .NET跨平台实践:.NetCore、.Net5/6 Linux守护进程设计

    几年前,我写过两篇关于用C#开发Linux守护进程的技术文章,分别是<.NET跨平台实践:用C#开发Linux守护进程.NET跨平台实践:再谈用C#开发Linux守护进程 - 完整篇 这就是本文 ...

  2. C# Net6开发Linux守护进程(后台服务程序,类似Windows服务)案例

    C# Net6开发Linux守护进程(后台服务程序,类似Windows服务)案例 背景 C# net6开发Linux守护进程要点 背景 在使用net6开发Linux程序时,除了AspNet Core项 ...

  3. .NET跨平台实践:用C#开发Linux守护进程

    Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon也能在后台正常工作. 一句话,为L ...

  4. Linux多进程开发(三)进程创建之守护进程的学习

       之前发过一篇守护进程的文章,但是解析的不够详细,这次,详细来解释守护进程的一些概念和特性.   概念: 后台运行.没有控制端与之相连的进程.独立于控制终端,通常周期性的执行某种任务.    Wh ...

  5. python全栈开发-再谈编码 python_day_6

    一. 回顾上周所有内容 一. python基础 Python是一门解释型. 弱类型语言 print("内容", "内容", end="\n" ...

  6. 再谈 Go 语言在前端的应用前景

    12 月 23 日,七牛云 CEO & ECUG 社区发起人许式伟先生在 ECUG Con 2018 现场为大家带来了主题为<再谈 Go 语言在前端的应用前景>的内容分享. 本文是 ...

  7. “云计算”三部曲之二:与“云”共舞——再谈云计算

    引言:去年,我曾在一篇名为<未来计算在"云-端">的文章中指出,纯"云计算"并不是启动计算未来的"万能钥匙","云+端 ...

  8. tensorflow和python先学哪个-前辈说先学会了这些Python知识点,再谈学习人工智能!...

    原标题:前辈说先学会了这些Python知识点,再谈学习人工智能! 首先我们看一看Python的优势: 开源,跨平台. 社区.不要小看这一点.社区意味着有很多教程.书籍,出了问题很容易google到,乃 ...

  9. 再谈编程范式-程序语言背后的思想

    link link 编程范式 托马斯.库尔提出"科学的革命"的范式论后,Robert Floyd在1979年图灵奖的颁奖演说中使用了编程范式一词.编程范式一般包括三个方面,以OOP ...

最新文章

  1. 浙大版《C语言程序设计(第3版)》题目集 练习2-17 生成3的乘方表 (15 分)
  2. 查看系统信息命令:uname
  3. 500 行代码写一个俄罗斯方块游戏
  4. 查看系统各个进程打开的文件描述符数量
  5. android adb install Failure,提示base.apkcode is missing问题的解决
  6. python链表的创建_python数据结构之链表的实例讲解
  7. 第九节:委托和事件(1)(委托的发展历史、插件式编程、多播委托)
  8. 高斯核函数python代码_单类SVM:SVDD
  9. 【转载翻译】Debian配置Networking 和 apt-get 源信息 开启root远程登录权限
  10. Day 5内存管理,定义变量
  11. case when的使用方法
  12. 使用Arduino开发板和颜色传感器区分不同颜色
  13. Http响应Response详解
  14. Java面向对象三大特征---继承
  15. 如何用java取对数_使用Java中的Math.log获取自然对数值
  16. kingbase之时间日期加减
  17. Hello Kitty
  18. 操作系统---页式地址重定位
  19. 一个类似JQuery的精简版框架
  20. Python+Vue计算机毕业设计高考填报志愿综合参考系统1kc8i(源码+程序+LW+部署)

热门文章

  1. linux命令chown和chmod什么区别
  2. 基于centos5.8源码安装nginx之LNMP
  3. Js黑客帝国效果 文字下落 制作过程和思路
  4. 闲来没事写个记事本玩玩!!!
  5. 【转】x.509证书在WCF中的应用(CS篇)
  6. ASP.NET Core使用功能开关控制路由访问(续)
  7. WPF 表格控件 ReoGrid 的简单使用
  8. 《.NET内存管理宝典》在京东上架销售啦!
  9. IdentityServer4之持久化很顺手的事
  10. 如何在 ASP.Net Core 使用 分布式缓存