免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: spiritX
打印 上一主题 下一主题

Unix下有什么方法实现防止程序多重执行? [复制链接]

论坛徽章:
0
41 [报告]
发表于 2009-02-07 12:05 |只看该作者

回复 #14 fera 的帖子

http://bbs.chinaunix.net/thread-904517-1-1.html

在AIX 下实践,不可使用,在上面的帖子里说明也是不可以使用的。。。

论坛徽章:
0
42 [报告]
发表于 2009-02-07 14:26 |只看该作者
原帖由 fera 于 2009-2-6 17:53 发表

目录项不会被立即删除,内核中的inode也存在,只是linkcount变成0了。
我用./a.out &执行,然后ls -a,照样可以看见。显然不是只有一个进程可以看见。


您真的做过实验了么,./a.out &执行后然后ls -a还能看到? 而且再次执行./a.out &会因为打印出ERROR?

希望您再试试,实际上正好相反:./a.out &执行后然后ls -a看不到hello文件,而且在第一个a.out还在运行时运行第二个a.out也不会打印出ERROR,换句话说,就是第二个a.out仍然成功执行了的CREATE函数。

unlink的这种用法是好东西,但不符合本帖的需求。unlink一个正在打开的文件是为了在后面仍然能够对其进行操作,而在程序崩溃后这个文件不会遗留下来。

unlink的实现大概是这样的:
a.找到这个文件对应的dir_entry结构,并把它的inode成员清0。这样就意味着这个文件已经不在文件系统中了(尽管内容还在),所以之后就找不到这个文件了,并且能再创建一个新的同名文件了。
b.把inode的i_nlink--,如果这个文件没有硬链接的话那么i_nlink就是0了
c.之后iput(inode)时由于该inode->i_count--后不为0(之前的create导致了一个占用),所以并不会truncate而是直接返回。
d.当进程退出(包括崩溃)时要关闭所有打开的文件,又会触发iput(inode),这时候inode->i_count--后inode->i_count就为0了,而且inode->i_nlink也已经为0,因此会继续向下执行调用truncate来释放文件占用的空间。

当然,如果系统突然掉电的话,文件的内容应该就没有机会释放了,可能有日志的文件系统会检查到并修正,希望了解这方面内容的兄弟大概介绍一下。

论坛徽章:
0
43 [报告]
发表于 2009-02-07 19:26 |只看该作者
原帖由 fedora_core_7 于 2009-2-7 14:26 发表


您真的做过实验了么,./a.out &执行后然后ls -a还能看到? 而且再次执行./a.out &会因为打印出ERROR?

希望您再试试,实际上正好相反:./a.out &执行后然后ls -a看不到hello文件,而且在第一个a.out还在 ...

我从来不让别人拿我没做过实验的代码来测试——不幸的是,这次我实验用的是cygwin,而不是用linux。我想当然以为都一样。

不同意a。我认为文件内容还在但inode不存在时,该文件的数据块将被系统回收。所以inode必须存在,而不会“把它的inode成员清0”。否则要读写unlink的文件,怎么查找数据在哪个磁盘块?其他理解与你相同。

有了对a的修正,就好理解突然掉电了。这时内存中的一切数据结构都没了,那么in-core-inode也没了。这时磁盘inode可能dirty,也可能是与unlink后的in-core-inode同步了。若磁盘inode是dirty,应该根据相应的日志记录来恢复;如果是同步过的,那么就没有问题,系统自动回收。

[ 本帖最后由 fera 于 2009-2-7 19:33 编辑 ]

论坛徽章:
0
44 [报告]
发表于 2009-02-07 20:45 |只看该作者
原帖由 fera 于 2009-2-7 19:26 发表

我从来不让别人拿我没做过实验的代码来测试——不幸的是,这次我实验用的是cygwin,而不是用linux。我想当然以为都一样。

不同意a。我认为文件内容还在但inode不存在时,该文件的数据块将被系统回收。所以 ...


我拿visual studio试验了一下,_unlink失败

论坛徽章:
0
45 [报告]
发表于 2009-02-08 00:56 |只看该作者

最好的实现方法.

使用共享内存的方式.

可以实现你的所有需求.

现实生产环境中有很多应用例子.

论坛徽章:
0
46 [报告]
发表于 2009-02-08 01:31 |只看该作者
原帖由 fera 于 2009-2-7 19:26 发表

我从来不让别人拿我没做过实验的代码来测试——不幸的是,这次我实验用的是cygwin,而不是用linux。我想当然以为都一样。

不同意a。我认为文件内容还在但inode不存在时,该文件的数据块将被系统回收。所以 ...



原来你是在cygwinx下做的实验,难怪了。cygwin最终应该也要通过win32sdk来实现unlink,可能用已有的win32sdk组合不能完全模拟POSIX unlink的行为。搜索cygwin+unlink能得到不少结果,比如 http://wiki.osdev.org/Cygwin_Issues 列举了一些cygwin的Unexpected Behaviour,关于unlink的就有一条:“unlink a file and subsequent creation of a new file in the same location is not supported” ,这也解释了为什么咱们的结果不一样。另外,我原来有同事还专门在windows下实验过windows本地的_unlink,结论是windows下无法用_unlink删除打开的文件,楼上兄弟说的就应该是这件事。看来这个讨论这个问题和系统关系很密切,windows、cygwin、*nix的行为都不一样。

至于我说的“找到这个文件对应的dir_entry结构,并把它的inode成员清0”,可能是我没表达清楚吧,我的意思不是把文件的inode清0,而是把文件对应的目录项的inode成员清0,拿ext2来举例吧,它是这样一个结构:
struct ext2_dir_entry_2 {
        __u32        inode;                        /* Inode number */
        __u16        rec_len;                /* Directory entry length */
        __u8        name_len;                /* Name length */
        __u8        file_type;
        char        name[EXT2_NAME_LEN];        /* File name */
};
这样说就应该没有歧义了。

还有你说最后提到的“若磁盘inode是dirty,应该根据相应的日志记录来恢复”中的dirty存在哪里,磁盘上?因为我只看到inode中是有dirty项,但它只存在内存中。希望你能解答一下,最好能告诉我相应的代码在哪。不清楚也无所谓,毕竟这是一个很专的问题了。

论坛徽章:
0
47 [报告]
发表于 2009-02-08 12:33 |只看该作者
怎么简单怎么来,省下的时间都是自己的

论坛徽章:
0
48 [报告]
发表于 2009-02-08 12:35 |只看该作者

回复 #13 nicksean 的帖子

这个正解

论坛徽章:
0
49 [报告]
发表于 2009-02-08 19:05 |只看该作者
我也来试试!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <sys/types.h>
#include <signal.h>

char *create_filename_dep_on_argv(char **argv)
{
&nbsp;&nbsp;&nbsp;&nbsp;return "/tmp/filename_dep_on_argv";
}

void
check_proc_use_file(char *filename)
{
&nbsp;&nbsp;&nbsp;&nbsp;FILE *fp = NULL;
&nbsp;&nbsp;&nbsp;&nbsp;char mod[] = "r+";
&nbsp;&nbsp;&nbsp;&nbsp;pid_t pid = 0;
&nbsp;&nbsp;&nbsp;&nbsp;if(access(filename,F_OK) != 0){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mod[0]='w';
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mod[1]=0;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;fp = fopen(filename,mod);
&nbsp;&nbsp;&nbsp;&nbsp;if(!fp){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror("ERROR\n");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;if(mod[0]=='r'){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fscanf(fp,"%d",&pid);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(pid > 0 &&  kill(pid,0) == 0){ ///判断进程是否存在

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror("I have to go :");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(2);//存在

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}else{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fseek(fp, 0L, SEEK_SET); //不存在

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(fp,"%d\n",getpid());
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}else{///这是第一次

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fseek(fp, 0L, SEEK_SET);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(fp,"%d\n",getpid());
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;fclose(fp);
}

int main(int argc,char **argv)
{
&nbsp;&nbsp;&nbsp;&nbsp;char *filename = create_filename_dep_on_argv(argv);
&nbsp;&nbsp;&nbsp;&nbsp;check_proc_use_file(filename);
&nbsp;&nbsp;&nbsp;&nbsp;printf("A new start .\n");
&nbsp;&nbsp;&nbsp;&nbsp;sleep(10);
&nbsp;&nbsp;&nbsp;&nbsp;remove(filename);
&nbsp;&nbsp;&nbsp;&nbsp;return 0;
}

论坛徽章:
0
50 [报告]
发表于 2009-02-08 20:54 |只看该作者
原帖由 fedora_core_7 于 2009-2-8 01:31 发表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&还有你说最后提到的“若磁盘inode是dirty,应该根据相应的日志记录来恢复”中的dirty存在哪里,磁盘上?因为我只看到inode中是有 dirty项,但它只存在内存中。希望你能解答一下,最好能告诉我相应的代码在哪。不清楚也无所谓,毕竟这是一个很专的问题了。

我不知道……不过我认为,磁盘上的inode应该提供某种检验标志吧?否则fsck无法工作啊。

[ 本帖最后由 fera 于 2009-2-8 21:18 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP