红联Linux门户
Linux帮助

程序如何在关机前保存内存里的数据到磁盘上呢?

发布时间:2006-09-05 18:24:10来源:红联作者:zhoulifa
假设自己写一个后台服务程序,开机后自动运行,并且永远在后台运行着。
如果其它用户通过其它命令(比如root用户输入reboot命令)或其它程序要关闭计算机,我们的程序如何开始保存自己的数据到磁盘上呢?能让系统等我们保存好数据后再关机吗?

首先,我们来做一个实验。各位查看一下自己的/etc/inittab看看这:
[code]
# The default runlevel.
id:2:initdefault:
[/code]

当然,大家知道这是当前运行级别。比如我这里是运行级别为2

然后,编写这样一个测试脚本/etc/init.d/my-start-stop,内容如下:

[code]
#! /bin/sh
set -e

# /etc/init.d/my-start-stop: start and stop test

case "$1" in
start)
echo -n "Starting my-start-stop server"
echo ""
sleep 10
;;
stop)
echo -n "Stopping my-start-stop server"
echo -n ""
sleep 10
;;
*)
echo "Usage: /etc/init.d/my-start-stop {start|stop}"
exit 1
esac

exit 0
[/code]
然后在当前运行级别所属目录/etc/rc2.d里面创建启动链接:
引用:

ln -s /etc/init.d/my-start-stop /etc/rc2.d/S70my-start-stop


在/etc/rc0.d目录里面创建关闭链接:

引用:

ln -s /etc/init.d/my-start-stop /etc/rc0.d/K11my-start-stop


输入halt -p命令关机看看吧,肯定能看到屏幕提示:
引用:

“Stopping my-start-stop server”

然后等待10秒钟。

再开机肯定会看到屏幕提示:
引用:

“Starting my-start-stop server”


如果大家感兴趣可以看一下我之前发的贴“Linux下XWindow系统启动脚本分析”
http://bbs.chinaunix.net/viewthread.php?tid=721285&highlight=zhoulifa

有了上面这个实验,我们就可以完成一个关机前保存数据的程序了。

首先,C程序代码如下:
[code]
#include
#include
#include
#include
#include
#include

#define SIGTOCAP SIGTERM

void sighandler(int);
char status;
time_t t;

/************关于本文档********************************************
*filename: SaveData.c
*purpose: 展示如何在关机前保存数据
*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2006-09-02 22:11:54
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/
int main(int argc, char ** argv)
{
FILE * fp = 0;

if(fork()) exit(0);
if(fork()) exit(0); /* 变成 daemon 精灵程序进行后台服务 */

signal(SIGTOCAP, sighandler); /* 捕捉退出信号 */
if(!(fp = fopen("/var/run/save-data.pid", "w"))) {
fprintf(stdout, "cannot open file '/var/run/save-data.pid'\n");
exit(1);
}
fprintf(fp, "%d\n", getpid()); /* 保存运行程序的 pid */
fclose(fp);

if(!(fp = fopen("/home/test/running.data", "a+"))) {
fprintf(stdout, "cannot open file '/home/test/running.data'\n");
exit(1);
}
status = 0;
while(1) {
t = time(0);
fprintf(fp, "now running at %s\n", ctime(&t)); /* 每隔一定时间写一些数据,表明程序在运行 */
if(status) break; /* 如果收到退出信号,并保存完数据, 则退出程序运行 */
usleep(1000000);
}
fclose(fp);
remove("/var/run/save-data.pid"); /* 退出前删除 pid 文件 */
return 0;
}

void sighandler(int sig)
{
FILE * fp = 0;
int i = 0;
if(sig == SIGTOCAP) { /* 捕捉到退出信号后开始保存数据 */
if(!(fp = fopen("/home/test/saving.data", "a+"))) {
fprintf(stdout, "cannot open file '/home/test/saving.data'\n");
exit(-1);
}
for(i = 0; i < 10000; i++) {
t = time(0);
fprintf(fp, "now get ready to exit at %s\n", ctime(&t));
}
fclose(fp);
status= 1; /* 数据保存完毕,设置退出标志 */
}
}
[/code]
然后编译此程序:
引用:

gcc SaveData.c -o save-data

再把这个程序放到/bin目录下去:

引用:

mv save-data /bin


然后编写一个脚本/etc/init.d/save-data,内容如下:

[code]
#!/bin/sh
#
# $Id: save-data.init.d,v 1.0.0.0 2006/09/02 22:11:54
#

test -x /bin/save-data || exit 0

MYPID=/var/run/save-data.pid

case "$1" in
start)
echo -n "Starting save-data daemon: "
echo -n ""
sleep 10 # Just for test , you'd better delete this line for use
start-stop-daemon --start --quiet --pidfile $MYPID --exec /bin/save-data
if [ -f "$MYPID" ] && ps h `cat "$MYPID"` >/dev/null; then
echo " OK."
else
echo " Failed."
fi
;;
stop)
echo -n "Stopping save-data daemon: save-data"
echo -n ""
sleep 10 # Just for test , you'd better delete this line for use
start-stop-daemon --stop --quiet --pidfile $MYPID
echo "."
;;
restart | force-reload)
$0 stop
sleep 2
$0 start
;;
*)
echo "Usage: /etc/init.d/save-data {start|stop|restart}"
exit 1
esac

exit 0
[/code]
再创建链接:

引用:

ln -s /etc/init.d/save-data /etc/rc2.d/S70save-data
ln -s /etc/init.d/save-data /etc/rc0.d/K10save-data


然后重启机器两次试试,会看到数据被保存到saving.data文件里了
文章评论

共有 2 条评论

  1. zhoulifa 于 2006-09-07 08:12:40发表:

    理论上肯定是可以的,而且现在的OS都有这功能了,关机时其中一个选项就是“休眠”
    但我自己没写过一个休眠程序 :(

  2. caitoad 于 2006-09-06 15:17:43发表:

    理论上来说,是可以做出类似windows中的休眠的功能的。
    能不能吧内存序列化,下次开机的时候然后再完全读回那?