我已经开发了一个C程序(Linux),这个程序创建一个新文件并写入,然后重新启动PC.
重启后,我丢失了程序创建的文件.当我停用重启功能时,我的程序创建的文件仍然存在.
在Linux上可以看到这种行为: - VirtualBox上的OpenWrt(Backfire 10.03)(文件系统ext2) - Linux(Ubuntu)(文件系统ext4)
您是否已解释此行为以及如何解决此问题?
#include <stdio.h>
#include <sys/reboot.h>
int main ()
{
FILE *pFile;
char mybuffer[80];
pFile = fopen ("/home/user/Desktop/example.txt","w");
if (pFile == NULL) perror ("Error opening file");
else
{
fputs ("test",pFile);
fclose (pFile);
}
rename("/home/user/Desktop/example.txt","/home/user/Desktop/example123.txt");
reboot(RB_AUTOBOOT);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当前的问题是,在重新启动之前不要同步文件.在实际的问题是,你拨打reboot直接系统调用,而不考虑还有什么是系统上发生的情况方面.你所做的与简单地按下硬件复位按钮非常相似; 你只是让内核有机会做一些清理工作,但随后一切都被杀死了.这是最终破坏文件系统和文件结构的可靠方法.不要这样做!.
相反,您应该要求init系统执行gracefull重新启动.调用reboot系统调用需要特权访问.所以你也可以要求init系统重启.在大多数系统上都有一个符号链接/sbin/reboot指向程序,如果通过该符号链接调用该程序将启动理智的重启.因此我建议你更换你的脏reboot(RB_AUTOBOOT)(请注意"/sbin/reboot"execlp中的双重规范- 这很重要).
pid_t reboot_pid;
if( 0 == (reboot_pid = fork()) ) {
execlp("/sbin/reboot", "/sbin/reboot", NULL);
exit(1); /* never reached if execlp succeeds. */
}
if( -1 == reboot_pid ) {
/* fork error... deal with it somehow */
}
int reboot_status;
waitpid(reboot_pid, &reboot_status, 0);
if( !WIFEXITED(reboot_status) ) {
/* reboot process did not exit sanely... deal with it somehow */
}
if( 0 != WIFEXITSTATUS(reboot_status) ) {
/* reboot process exited with error;
* most likely the user lacks the required privileges */
}
else {
fputs("reboot call sucessfull -- system is about to shutdown.");
/* The init system is now shutting down the system. It will signals all
* programs to terminate by sending SIGTERM, followed by SIGKILL to
* programs that didn't terminate gracefully. */
}
Run Code Online (Sandbox Code Playgroud)
这样做可以使系统正常关闭,以干净的方式终止所有运行的程序,并在重新启动之前卸载所有文件系统,从而保证文件系统和数据的完整性.
请注意,如果您希望您的程序不具有root访问权限,那么您将不得不跳过一些箍; 在具有systemd的系统上,您可以通过D-Bus发送重启请求.但是除了失败之外,如果执行命令的用户没有重启权限.
| 归档时间: |
|
| 查看次数: |
8991 次 |
| 最近记录: |