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守护进程 — 完整篇的更多相关文章

  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. 巨蟒python全栈开发linux之centos6 第二篇

    1. .nginx负载均衡的实现 .准备三台机器,准备3台虚拟机,或者和俩同桌交流一下 192.168.226.128 是nginx资源服务器,返回页面的 192.168.226.129 用作ngin ...

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

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

随机推荐

  1. c++中typedef、define、const、inline之间的区别

    1.typedef和#define的区别 typedef int* pInt; , b = ; const pInt p1 = &a; //p1是常量指针 pInt const p2 = &a ...

  2. SpringBoot2.0.2 Application调用的三种方式

    一.注解 @SpringBootApplication            点开查看源码是由多个注解合成的注解,其中主要的注解有:            @SpringBootConfigurati ...

  3. CodeForces 916C Jamie and Interesting Graph (构造)

    题意:给定两个数,表示一个图的点数和边数,让你构造出一个图满足 1-  n 的最短路是素数,并且最小生成树也是素数. 析:首先 1 - n 的最短路,非常好解决,直接 1 连 n 就好了,但是素数尽量 ...

  4. [转]MySQL源码:Range和Ref优化的成本评估

    MySQL源码:Range和Ref优化的成本评估 原文链接:http://www.orczhou.com/index.php/2012/12/mysql-source-code-optimizer-r ...

  5. 文档/视图(01):第一个Demo

    学习文档视图编程的第一个demo,程序比较简单,主要对文档模板,文档,视图等相互关系的一个了解. 功能:菜单添加一个[操作]项,然后新建四份空白文档,点击[操作]之后,在四份空白文档上面各绘制一个Bu ...

  6. Warning the user/local/mysql/data directory is not owned by the mysql user

    sudo chown -RL root:mysql /usr/local/mysql sudo chown -RL mysql:mysql /usr/local/mysql/data sudo /us ...

  7. Maven之java application _HelloWord

    maven  是一个项目构建的一个工具; 一.环境的配置; 1.下载maven 解压放在一个路径下为了好找我们就将该文件放在 D:\javaNew\apache-maven-3.3.9 2.配置本地仓 ...

  8. 在linux中如何解压.tgz

    然后首先:打开终端 1,进入下载路径下,比如我的就是进入Downloads下. 输入命令: cd Downloads 2,解压到当前文件夹 输入:tar zxvf  文件名.tgz -C ./     ...

  9. SSM_CRUD新手练习(5)测试mapper

    上一篇我们使用逆向工程生成了所需要的bean.dao和对应的mapper.xml文件,并且修改好了我们需要的数据库查询方法. 现在我们来测试一下DAO层,在test包下新建一个MapperTest.j ...

  10. 关于QT建立项目中遇到的相关问题的处理办法

    关于QT建立项目中遇到的相关问题的处理办法 1.在QTCreater中新建一个空的工程时,第一次运行会抱一个错误,如下: -1: error: LNK1123: 转换到 COFF 期间失败: 文件无效 ...