.NET跨平台实践:再谈用C#开发Linux守护进程 — 完整篇
2021-04-25 03:29
标签:dom exe 功能 代码 manage port rem imp private Linux守护进程是Linux的后台服务进程,相当于Windows服务,对于为Linux开发服务程序的朋友来说,Linux守护进程相关技术是必不可少的,因为这个技术不仅仅是为了开发守护进程,还可以拓展到多进程,父子进程文件描述符共享,父子进程通讯、控制等方面,是实现Linux大型服务的基础技术之一。 去年我也曾写了一篇关于守护进程的帖子,名字叫《.NET跨平台实践:用C#开发Linux守护进程》,这篇文章的的确确实现了一个Daemon,不过,它有一个弱点,不能运行多线程! 这篇帖子的目的就是进一步完善,让我们写出一个功能完整,可以用于生产环节的基本的守护进程。 先帖代码(假设项目名是daemon): 以上代码的工作过程是:判断程序自身是否已经处于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打印了一行字符。 .NET跨平台实践:再谈用C#开发Linux守护进程 — 完整篇 标签:dom exe 功能 代码 manage port rem imp private 原文地址:http://www.cnblogs.com/microtiger/p/7927612.html 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 /********************************************
10 * 一个完整的linux daemon示例,作者宇内流云 *
11 ********************************************/
12
13 namespace daemon
14 {
15 class Program
16 {
17
18 const string DaemonTag = "--daemon.";
19 static void Main(string[] args)
20 {
21 // 判断是否已经进入Daemon状态,如果是,就直接执行后台主函数
22 if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable(DaemonTag)) == false)
23 {
24 Environment.SetEnvironmentVariable(DaemonTag, null);
25 DaemonMain(args);
26 return;
27 }
28
29
30 // 如果还没有进入daemon状态,就作daemon处理
31 /////////////////////////////////////////////////////
32
33 int pid = fork();
34 if (pid != 0) exit(0);
35 setsid();
36 pid = fork();
37 if (pid != 0) exit(0);
38 umask(0);
39
40
41 // 这儿已经进入“守护进程”工作状态了!
42
43 // 关闭所有打开的文件描述符
44 int max = open("/dev/null", 0);
45 for (var i = 0; i 2)
59 {
60 for (var i = 0; i
72 /// Daemon工作状态的主方法
73 ///
74 ///
75 static void DaemonMain(string[] aargs)
76 {
77 //启动一个线程去处理一些事情
78 (new Thread(DaemonWorkFunct) { IsBackground = true }).Start();
79
80
81 //daemon时,控制台输入、输出流已经关闭
82 //请不要再用Console.Write/Read等方法
83
84 //阻止daemon进程退出
85 (new AutoResetEvent(false)).WaitOne();
86
87 }
88
89
90 static FileStream fs;
91 static int count = 0;
92 static void DaemonWorkFunct() {
93 fs = File.Open("/tmp/daemon.txt", FileMode.OpenOrCreate);
94 var t = new System.Timers.Timer() { Interval = 1000 };
95 t.Elapsed += OnElapsed;
96 t.Start();
97 }
98 private static void OnElapsed(object sender, ElapsedEventArgs e)
99 {
100 var s = DateTime.Now.ToString("yyy-MM-dd HH:mm:ss") + "\n";
101 var b = Encoding.ASCII.GetBytes(s);
102 fs.Write(b, 0, b.Length);
103 fs.Flush();
104
105 count++;
106 if (count > 100) {
107 fs.Close();
108 fs.Dispose();
109 exit(0);
110 }
111
112 }
113
114
115
116 [DllImport("libc", SetLastError = true)]
117 static extern int fork();
118
119 [DllImport("libc", SetLastError = true)]
120 static extern int setsid();
121
122 [DllImport("libc", SetLastError = true)]
123 static extern int umask(int mask);
124
125 [DllImport("libc", SetLastError = true)]
126 static extern int open([MarshalAs(UnmanagedType.LPStr)]string pathname, int flags);
127
128 [DllImport("libc", SetLastError = true)]
129 static extern int close(int fd);
130
131 [DllImport("libc", SetLastError = true)]
132 static extern int exit(int code);
133
134 [DllImport("libc", SetLastError = true)]
135 static extern int execvp([MarshalAs(UnmanagedType.LPStr)]string file, string[] argv);
136
137
138 }
139
140 }
文章标题:.NET跨平台实践:再谈用C#开发Linux守护进程 — 完整篇
文章链接:http://soscw.com/index.php/essay/79231.html