先试着写一个udpserver的daemon

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 4444
#define FDMAX 64
void initdaemon();
int main()
{
#ifdef DAEMON
initdaemon();
#endif
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if(fd < 0)
return -1;
struct sockaddr_in server, client;
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = htonl(INADDR_ANY);
bind(fd, (const struct sockaddr *)&server, sizeof(struct sockaddr));
socklen_t len = sizeof(struct sockaddr);
char buff[2048] = {0};
while(1)
{
recvfrom(fd, buff, 2048, 0,(struct sockaddr *)&client, &len);
// printf("%s send msg: %s \n", inet_ntoa(client.sin_addr), buff);
sendto(fd, "OK", 2, 0, (const struct sockaddr *)&client, len);
}
}
void initdaemon()
{
pid_t pid = fork(); //第一次fork 是因为创建会话的进程不能是进程组长,否则setsid会失败。
if(pid > 0)
{
_exit(0);
}
else if(pid < 0)
{
_exit(1);
}
if(setsid() < 0)
_exit(1);
pid_t id = fork();//第二次fork是因为当前进程是会话组长 他有可能会获取控制终端,为了不让它获得控制终端,不让它成为组长。
if(id > 0){
_exit(0);
}
else if(id < 0)
{
_exit(1);
}
int i = 0;
chdir("/");
for(i; i < FDMAX; ++i)
close(i);
open("/dev/null", O_RDONLY);
open("/dev/null", O_RDWR);
open("/dev/null", O_RDWR); //将0 1 2重定向
}
gcc -DDAEMON udpserver.c -o udpserver添加宏DAEMON进行编译

下面是测试client端:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 4444
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("./udpclient IP\n");
return 1;
}
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
return 1;
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
if (!inet_pton(AF_INET, argv[1], (void *)&server.sin_addr))
{
printf("IP error\n");
return -1;
}
char buff1[2048] ="sdfsdf";
char buff2[2048] = {0};
socklen_t size = sizeof(struct sockaddr);
while(1)
{
sendto(fd, buff1, 2048, (const struct sockaddr *)&server, size);
sleep(5);
recvfrom(fd, buff2, 2048, 0, NULL, NULL);
printf("recv : %s\n", buff2);
} }

先看一下system v init管理服务的一种写法:
我们可以看到在/etc/init.d 下面有很多脚本文件, 当系统启动时,init进程会根据不同的运行级别去执行不同的/etc/rcN.d 里面的脚本文件并会自动加上start参数,我们看一下sshd的例子:

set -e

# /etc/init.d/ssh: start and stop the OpenBSD "secure shell(tm)" daemon

test -x /usr/sbin/sshd || exit 0
( /usr/sbin/sshd -\? 2>&1 | grep -q OpenSSH ) 2>/dev/null || exit 0 umask 022 if test -f /etc/default/ssh; then
. /etc/default/ssh
fi 略 case "$1" in
start)
check_for_upstart 1
check_privsep_dir
check_for_no_start
check_dev_null
log_daemon_msg "Starting OpenBSD Secure Shell server" "sshd" || true
if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS; then
log_end_msg 0 || true
else
log_end_msg 1 || true
fi
;;
stop)
check_for_upstart 0
log_daemon_msg "Stopping OpenBSD Secure Shell server" "sshd" || true
if start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/sshd.pid; then
log_end_msg 0 || true
else
log_end_msg 1 || true
fi
;; reload|force-reload)
check_for_upstart 1
check_for_no_start
check_config
log_daemon_msg "Reloading OpenBSD Secure Shell server's configuration" "sshd" || true
if start-stop-daemon --stop --signal 1 --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd; then
log_end_msg 0 || true
else
log_end_msg 1 || true
fi
;; restart)
check_for_upstart 1
check_privsep_dir
check_config
log_daemon_msg "Restarting OpenBSD Secure Shell server" "sshd" || true
start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile /var/run/sshd.pid
check_for_no_start log_end_msg
check_dev_null log_end_msg
if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS; then
log_end_msg 0 || true
else
log_end_msg 1 || true
fi
;; try-restart)
check_for_upstart 1
check_privsep_dir
check_config
log_daemon_msg "Restarting OpenBSD Secure Shell server" "sshd" || true
RET=0
start-stop-daemon --stop --quiet --retry 30 --pidfile /var/run/sshd.pid || RET="$?"
case $RET in
0)
# old daemon stopped
check_for_no_start log_end_msg
check_dev_null log_end_msg
if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS; then
log_end_msg 0 || true
else
log_end_msg 1 || true
fi
;;
1)
# daemon not running
log_progress_msg "(not running)" || true
log_end_msg 0 || true
;;
*)
# failed to stop
log_progress_msg "(failed to stop)" || true
log_end_msg 1 || true
;;
esac
;; status)
check_for_upstart 1
status_of_proc -p /var/run/sshd.pid /usr/sbin/sshd sshd && exit 0 || exit $?
;; *)
log_action_msg "Usage: /etc/init.d/ssh {start|stop|reload|force-reload|restart|try-restart|status}" || true
exit 1
esac exit 0

写法也就是大致这个样子的利用shell 里的case 给不同参数运行不同的function 至于start-stop-daemon的用法可以查阅man page。
我们就可以将我们的udpserver 放到/usr/bin/目录下面,然后在/etc/init.d/目录下加上udp_server 脚本文件写法如下:

 #!/bin/bash
SERVER=/usr/bin/udpserver
if [ ! -e $SERVER ];then
exit 1
fi
case "$1" in
start)
if [ -n "`pidof $SERVER`" ];then
echo "Udpserver is running......"
else
$SERVER
fi
;; stop)
PID=`pidof /usr/bin/udpserver`
[ -n "$PID" ] && kill -9 $PID
;; restart)
PID=`pidof $SERVER`
[ -n "$PID" ] && kill -9 $PID
$SERVER
;; *)
exit 1
;; esac

再将你需要运行的等级目录下添加连接/etc /rc2.d/目录下K开头表示不启动服务,S打头表示启动服务 建立连接 ln -s ../init.d/udp_server S99udpserver , 表名开机启动 S后的数字字母等表示启动顺序。如此就可以实现system v init类型的启动服务。

若以systemd形式 将更为简单方便 此时就不需要udpserver 是一个daemon 可去掉宏进行编译。

在/etc/systemd/system/下建立文件udpserver.service 文件 内容大概为

[Unit]
Description=my dup server
After=network.target [Service]
EnvironmentFile=
ExecStart=/usr/bin/udpserver
ExecReload=/bin/killall udpserver
KillMode=process
Restart=on-failure [Install]
WantedBy=multi-user.target

然后再执行 systemctl daemon-reload systemctl enable udpserver即可开机自启动。
systemctl start /stop/reload控制服务。journalctl可以查看启动日志。
总得来说还是systemd这种形式较为简单,它还有较好的日志系统,方便管理 不用将服务写为daemon。

daemon 启动system V init 和 systemd 配置的更多相关文章

  1. 编写CentOS的System V init启动脚本

    系统本身自带了说明,在/usr/share/doc/initscripts-(*)/sysvinitfiles,内容如下: 所有System V init脚本都命名为/etc/rc.d/init.d/ ...

  2. Systemd初始化进程/RHEL 6系统中System V init命令与RHEL 7系统中systemctl命令的对比

    Linux操作系统的开机过程是这样的,即从BIOS开始,然后进入Boot Loader,再加载系统内核,然后内核进行初始化,最后启动初始化进程.初始化进程作为Linux系统的第一个进程,它需要完成Li ...

  3. systemd、upstart和system V

    http://blog.csdn.net/kumu_linux/article/details/7653802  systemd是Linux下的一种init软件,由Lennart Poettering ...

  4. Linux system V

    Sysvinit 的小结 Sysvinit 的优点是概念简单.Service 开发人员只需要编写启动和停止脚本,概念非常清楚:将 service 添加/删除到某个 runlevel 时,只需要执行一些 ...

  5. /etc/init.d/sshd配置SSHD路径忘记修改导致启动失败

    [root@lnlte2dmr3 ~]# bash[root@lnlte2dmr3 ~]# install -v -m700 -d /var/empty/sshdinstall: 正在创建目录&quo ...

  6. Linux启动流程和服务管理(init和systemd)

    目录 一:Linux启动流程 init和Systemd的区别 二:Linux服务管理(service,systemctl) 一:Linux启动流程 Rhel6启动过程: Rhel7启动过程: GRUB ...

  7. Linux init 系列一 System V风格

    传统的Linux init有两种风格,System V风格和BSD风格,本文主要介绍System V风格. System V风格init的主要流程是, 1. 内核执行init进程. 2. Init 运 ...

  8. System V启动脚本启动的服务

    /etc/rc.d/init.d/目录下的内容如下:这些常用的服务器都是System v的服务,要控制System V 的服务,我们可以使用以下命令 #/etc/rc.d/init.d/script  ...

  9. 提示“应用程序无法启动,因为应用程序的并行配置不正确”不能加载 System.Data.SQLite.dll

    新版本SQLITE,如果下载Precompiled Binaries版会出现提示“应用程序无法启动,因为应用程序的并行配置不正确”不能加载 System.Data.SQLite.dll. 下载Prec ...

随机推荐

  1. 461. Hamming Distance(leetcode)

    The Hamming distance between two integers is the number of positions at which the corresponding bits ...

  2. Ubuntu远程登陆、SSH图形界面、WOL远程唤醒

    本文为作者原创,转载请注明出处(http://www.cnblogs.com/mar-q/)by 负赑屃 实现目标:通过路由器配置路由路径,将拨号获取的公网IP地址指向局域网Ubuntu服务器.家里有 ...

  3. iOS之创建一个常驻线程

    // 当创建一个线程,并且希望它一直存在时,但往往我们创建的线程都是执行完成之后也就停止了,不能再次利用,那么如何创建一个线程可以让他可以再次工作呢,这个时候就需要使用到RunLoop了.下面的是我写 ...

  4. Android的主线程和子线程

    在一个Android 程序开始运行的时候,会单独启动一个Process.默认的情况下,所有这个程序中的Activity或者Service(Service和 Activity只是Android提供的Co ...

  5. 5.volatile的应用

    volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的"可见性".可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值.如果v ...

  6. indexed database IndexedDB

    Indexed Database API 目的是提供一个可供javascript存储和检索对象,并且还能进行查询,搜索等数据库操作   设计为几乎完全异步,因此绝大部分操作都稍后执行,因此每次操作都应 ...

  7. 离线缓存 manifest

    程序的离线缓存由一个叫做manifest的文本文件控制,把需要离线缓存的文件列在里面即可,这个列表还可以控制需要缓存的情况,甚至当用户从缓存地址进入到没有缓存的地址应该显示什么 当浏览器下载解析了ma ...

  8. 网页静态化技术Freemarker的详细介绍

    网页静态化技术Freemarker 一.Freemarker的基本介绍 1.1为什么要使用网页静态化技术 网页静态化解决方案在实际开发中运用比较多,例如新闻网站,门户网站中的新闻频道或者是文章类的频道 ...

  9. 一:Redis的7个应用场景

    Redis的7个应用场景   一:缓存——热数据 热点数据(经常会被查询,但是不经常被修改或者删除的数据),首选是使用redis缓存,毕竟强大到冒泡的QPS和极强的稳定性不是所有类似工具都有的,而且相 ...

  10. [转载] kill命令

    转载自http://www.cnblogs.com/peida/archive/2012/12/20/2825837.html Linux中的kill命令用来终止指定的进程(terminate a p ...