Linux守护进程是Linux的后台服务进程,相当于Windows服务,对于为Linux开发服务程序的朋友来说,Linux守护进程相关技术是必不可少的,因为这个技术不仅仅是为了开发守护进程,还可以拓展到多进程,父子进程文件描述符共享,父子进程通讯、控制等方面,是实现Linux大型服务的基础技术之一。

去年我也曾写了一篇关于守护进程的帖子,名字叫《.NET跨平台实践:用C#开发Linux守护进程》,这篇文章的的确确实现了一个Daemon,不过,它有一个弱点,不能运行多线程!

这篇帖子的目的就是进一步完善,让我们写出一个功能完整,可以用于生产环节的基本的守护进程。

先帖代码(假设项目名是daemon):

  1. using System;
  2. using System.Threading;
  3. using System.Timers;
  4. using System.Runtime.InteropServices;
  5. using System.IO;
  6. using System.Text;
  7.  
  8. /********************************************
  9. * 一个完整的linux daemon示例,作者宇内流云 *
  10. ********************************************/
  11.  
  12. namespace daemon
  13. {
  14. class Program
  15. {
  16.  
  17. const string DaemonTag = "--daemon.";
  18. static void Main(string[] args)
  19. {
  20. // 判断是否已经进入Daemon状态,如果是,就直接执行后台主函数
  21. if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable(DaemonTag)) == false)
  22. {
  23. Environment.SetEnvironmentVariable(DaemonTag, null);
  24. DaemonMain(args);
  25. return;
  26. }
  27.  
  28. // 如果还没有进入daemon状态,就作daemon处理
  29. /////////////////////////////////////////////////////
  30.  
  31. int pid = fork();
  32. if (pid != ) exit();
  33. setsid();
  34. pid = fork();
  35. if (pid != ) exit();
  36. umask();
  37.  
  38. // 这儿已经进入“守护进程”工作状态了!
  39.  
  40. // 关闭所有打开的文件描述符
  41. int max = open("/dev/null", );
  42. for (var i = ; i <= max; i++) { close(i); }
  43.  
  44. // 设置标记,防止重复运行进入
  45. Environment.SetEnvironmentVariable(DaemonTag,"yes");
  46.  
  47. //为execp参数重组参数
  48. var args1 = args == null ? new string[] : new string[args.Length + ];
  49.  
  50. args1[] = "MyDaemon";
  51. args1[] = Path.Combine(Environment.CurrentDirectory, Thread.GetDomain().FriendlyName);
  52.  
  53. if (args1.Length > )
  54. {
  55. for (var i = ; i < args.Length; i++)
  56. { args1[i + ] = args[i]; }
  57. }
  58.  
  59. //守护状态下重新加载和运行本程序
  60. execvp("mono", args1);
  61.  
  62. }
  63.  
  64. /// <summary>
  65. /// Daemon工作状态的主方法
  66. /// </summary>
  67. /// <param name="aargs"></param>
  68. static void DaemonMain(string[] aargs)
  69. {
  70. //启动一个线程去处理一些事情
  71. (new Thread(DaemonWorkFunct) { IsBackground = true }).Start();
  72.  
  73. //daemon时,控制台输入、输出流已经关闭
  74. //请不要再用Console.Write/Read等方法
  75.  
  76. //阻止daemon进程退出
  77. (new AutoResetEvent(false)).WaitOne();
  78.  
  79. }
  80.  
  81. static FileStream fs;
  82. static int count = ;
  83. static void DaemonWorkFunct() {
  84. fs = File.Open("/tmp/daemon.txt", FileMode.OpenOrCreate);
  85. var t = new System.Timers.Timer() { Interval = };
  86. t.Elapsed += OnElapsed;
  87. t.Start();
  88. }
  89. private static void OnElapsed(object sender, ElapsedEventArgs e)
  90. {
  91. var s = DateTime.Now.ToString("yyy-MM-dd HH:mm:ss") + "\n";
  92. var b = Encoding.ASCII.GetBytes(s);
  93. fs.Write(b, , b.Length);
  94. fs.Flush();
  95.  
  96. count++;
  97. if (count > ) {
  98. fs.Close();
  99. fs.Dispose();
  100. exit();
  101. }
  102.  
  103. }
  104.  
  105. [DllImport("libc", SetLastError = true)]
  106. static extern int fork();
  107.  
  108. [DllImport("libc", SetLastError = true)]
  109. static extern int setsid();
  110.  
  111. [DllImport("libc", SetLastError = true)]
  112. static extern int umask(int mask);
  113.  
  114. [DllImport("libc", SetLastError = true)]
  115. static extern int open([MarshalAs(UnmanagedType.LPStr)]string pathname, int flags);
  116.  
  117. [DllImport("libc", SetLastError = true)]
  118. static extern int close(int fd);
  119.  
  120. [DllImport("libc", SetLastError = true)]
  121. static extern int exit(int code);
  122.  
  123. [DllImport("libc", SetLastError = true)]
  124. static extern int execvp([MarshalAs(UnmanagedType.LPStr)]string file, string[] argv);
  125.  
  126. }
  127.  
  128. }

以上代码的工作过程是:判断程序自身是否已经处于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守护进程的更多相关文章

  1. .NET跨平台实践:再谈用C#开发Linux守护进程 — 完整篇

    Linux守护进程是Linux的后台服务进程,相当于Windows服务,对于为Linux开发服务程序的朋友来说,Linux守护进程相关技术是必不可少的,因为这个技术不仅仅是为了开发守护进程,还可以拓展 ...

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

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

  3. C#开发Linux守护进程

    用C#开发Linux守护进程   Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon ...

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

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

  5. .NET跨平台实践:用C#开发Linux守护进程(转)

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

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

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

  7. linux守护进程编写实践

    主要参考:http://colding.bokee.com/5277082.html (实例程序是参考这的) http://wbwk2005.blog.51cto.com/2215231/400260 ...

  8. Linux C++ 开发简介(包括Linux守护线程)

    阅读目录 简介 操作系统 编辑器 编译器 构建系统 调试 IDE 可执行程序.动态库.静态库 服务 Windows服务简介 创建Windows服务 注册Windows服务 管理Windows服务 Li ...

  9. C++ Primer 学习笔记_32_STL实践与分析(6) --再谈string类型(下)

    STL实践与分析 --再谈string类型(下) 四.string类型的查找操作 string类型提供了6种查找函数,每种函数以不同形式的find命名.这些操作所有返回string::size_typ ...

随机推荐

  1. 用php+mysql+ajax+jquery做省市区三级联动

    要求:写一个省市区(或者年月日)的三级联动,实现地区或时间的下拉选择. 实现技术:php ajax 实现:省级下拉变化时市下拉区下拉跟着变化,市级下拉变化时区下拉跟着变化. 使用chinastates ...

  2. ST HW3

    7. Use the following method printPrimes() for questions a-f below. /******************************** ...

  3. servlet匹配规则和顺序

    1.  写法 ①完全匹配:以“/”开头,以字母(非“*”)结束    如:<url-pattern>/test/list.do</url-pattern> ②目录匹配:以“/” ...

  4. lnmp pathinfo问题

    location / {              if (!-e $request_filename) {              rewrite  ^/(.*)$  /index.php/$1  ...

  5. Weexpack 使用教程

    简介 weexpack 是 weex 新一代的工程开发套件,是基于weex快速搭建应用原型的利器.它能够帮助开发者通过命令行创建weex工程,添加相应平台的weex app模版,并基于模版从本地.Gi ...

  6. Linux shell-grep

    grep --help备忘录 Usage: grep [OPTION]... PATTERN [FILE]...Search for PATTERN in each FILE or standard ...

  7. css3渐变生成器网页

    http://westciv.com/tools/gradients/ http://www.colorzilla.com/gradient-editor/

  8. 如何给sublime text3安装汉化包?so easy 哦

    这是我本人亲身测试过的,肯定有效,没用的话怪我咯. 首先安装package control,然后安装汉化包即可,很简单哦!!! 1.安装package control:打开sublime,使用快捷键: ...

  9. cassandra高级操作之分页的java实现(有项目具体需求)

    接着上篇博客,我们来谈谈java操作cassandra分页,需要注意的是这个分页与我们平时所做的页面分页是不同的,具体有啥不同,大家耐着性子往下看. 上篇博客讲到了cassandra的分页,相信大家会 ...

  10. 初识Object-C

    Object-C是苹果推出用来开发苹果软件的一门编程语言.大学学了3年的JAVA,到了大四毅然决然的放弃JAVA,是因为第一次接触Object-C就被它的简单语法吸引了.其实不仅仅是语法简单,相对于A ...