文件锁的使用问题。怎么没锁住啊?

树无影 2011-08-17 09:11:01
/*********************************************************************************/
/*
文件锁的使用。

*/
/********************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

void * fun(void * arg)
{
FILE *fp;
char buf[10] = "hello!";
char buf2[10] = {'\0'};

printf("in pthread:%x %x\n", getpid(), pthread_self());

if ((fp = fopen("1.txt", "w+")) == NULL)
{
printf("open error!\n");
}

if (ftrylockfile(fp) != 0)
{
printf("flockfile error!\n");
}

flockfile(fp);

fwrite(buf, sizeof (char), 7, fp);
rewind(fp);
fread(buf2, sizeof(char), 6, fp);

fputs(buf2, stdout);
//funlockfile(fp);

fclose(fp);

return (void *)0;
}

int main()
{
pthread_t tid;
int err;
FILE *fp;
char buf[10] = "hello!";
char buf2[10] = {'\0'};

if ((err = pthread_create(&tid, NULL, fun, NULL)) != 0)
{
printf("pthread error!\n");
}

if ((fp = fopen("1.txt", "w+")) == NULL)
{
printf("open error!\n");
}

if (ftrylockfile(fp) != 0)
{
printf("flockfile error!\n");
}

flockfile(fp);

fwrite(buf, sizeof (char), 7, fp);
rewind(fp);
fread(buf2, sizeof(char), 6, fp);

fputs(buf2, stdout);
//funlockfile(fp);

sleep(3); //如果主线程运行完了,子线程没运行完就结束了。

printf("in main:%x %x\n", getpid(), pthread_self());
printf("%d\n", pthread_equal(tid, pthread_self()));

fclose(fp);

return 0;
}

运行结果:
[root@localhost work1]# ./1
hello!in pthread:3653 b7f42b90
hello!in main:3653 b7f436c0
0
[root@localhost work1]#

怎么没锁住啊?
...全文
174 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
树无影 2011-08-19
  • 打赏
  • 举报
回复
我觉得锁得目的是实现一个进程再写完之后,没释放锁得话,其他的进程是不能再上锁的,也不能对锁得数据区操作。直到释放了写锁时,其他进程才能对文件进行操作。
树无影 2011-08-19
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 wanchangjiu123 的回复:]
你没看懂我的程序 呵呵,
是这样的 两个进程对同一个文件写数据,我是一秒钟写一个字符 父进程写A 子进程写a
如果不采用锁,就完全有可能出现 a与A互相相隔,出现了父进程与子进程的竞争。

aaaaaaaaaaAAAAAAAAAA 结果当然是这样,当一个进程对文件操作完了以后,另一个进程才对文件操作,就避开了竞争,锁的目的不是这样吗
[/Quote]我知道你的意思是父子进程可以会出现竞争的情况,但是不一定这种竞争会体现在程序里面。有的时候没体现的。我用父子进程同步读写来操作,就是为了避免在你的子进程读完后会结束,那么他的锁就自动释放了。对父进程的锁就没影响了。所以我子进程写完之后,并不推出。再让父进程写,结果还是写的进去。这就是我的疑问。
wanchangjiu123 2011-08-19
  • 打赏
  • 举报
回复
你没看懂我的程序 呵呵,
是这样的 两个进程对同一个文件写数据,我是一秒钟写一个字符 父进程写A 子进程写a
如果不采用锁,就完全有可能出现 a与A互相相隔,出现了父进程与子进程的竞争。

aaaaaaaaaaAAAAAAAAAA 结果当然是这样,当一个进程对文件操作完了以后,另一个进程才对文件操作,就避开了竞争,锁的目的不是这样吗
ssissi821 2011-08-19
  • 打赏
  • 举报
回复
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

void * fun(void * arg)
{
FILE *fp=(FILE*)arg;
char buf[20] = "fun hello!";
char buf2[20] = {'\0'};

printf("in pthread:%x %x\n", getpid(), pthread_self());

if (ftrylockfile(fp) != 0)
{
printf("flockfile error!\n");
}

flockfile(fp);

fwrite(buf, sizeof(char), 20, fp);
rewind(fp);
fread(buf2, sizeof(char), 20, fp);

fputs(buf2, stdout);
//funlockfile(fp);

return (void *)0;
}

int main()
{
pthread_t tid;
int err;
FILE *fp;
char buf[20] = "main hello!";
char buf2[20] = {'\0'};

if ((fp = fopen("1.txt", "w+")) == NULL)
{
printf("open error!\n");
}

if ((err = pthread_create(&tid, NULL, fun, (void *)fp)) != 0)
{
printf("pthread error!\n");
fclose(fp);
}

if (ftrylockfile(fp) != 0)
{
printf("flockfile error!\n");
}
printf("file is unlock\n");

flockfile(fp);

printf("file cand been locked\n");
fwrite(buf, sizeof (char), 20, fp);
rewind(fp);
fread(buf2, sizeof(char), 20, fp);

fputs(buf2, stdout);
//funlockfile(fp);

sleep(3); //如果主线程运行完了,子线程没运行完就结束了。

printf("in main:%x %x\n", getpid(), pthread_self());
printf("%d\n", pthread_equal(tid, pthread_self()));

fclose(fp);

return 0;
}

简单给你调了一下:如上代码,程序运行时由于主线程需要等待子线程解锁,因此主线程会一直停留在
printf("file is unlock\n");

flockfile(fp);

1.txt中会write进去的数据为:fun hello!即子进程的输入。父进程在等待解锁,所以数据无法写入的。
后续你需要将锁解开,让程序进入正常运行状态。
否则此程序就挂到等锁得状态,会出现死锁。

ssissi821 2011-08-19
  • 打赏
  • 举报
回复
忘记把fun函数中的fclose(fp); 删除了。
二个修改部分:
第一个:main中:
FILE *fp=(FILE*)arg;

if ((fp = fopen("1.txt", "w+")) == NULL)
{
printf("open error!\n");
}

if ((err = pthread_create(&tid, NULL, fun, (void *)fp)) != 0)
{
printf("pthread error!\n");
fclose(fp);
}
即先打开文件,并且获得文件句柄fp,然后再创建线程fun,其中线程的参数为fp。

第二个修改:
线程函数fun中去掉打开文件1.txt操作,打开的文件句柄fp接收来自main中创建线程函数的句柄。
FILE *fp=(FILE*)arg;
这样就保证了二者操作的是同一个1.txt文件句柄,加锁时main中和fun中加锁加的才是同一个文件锁。
这样写入到1.txt就只有fun函数中的hello。

另外,建议你测试时把main中和fun中写入到1.txt的数据分开,都弄成hello,写入的都不知道是main写的还是fun写的。例如改成:很清晰可以看到1.txt中是谁写的。
char buf[10] = "main hello!";
char buf[10] = "fun hello!";
ssissi821 2011-08-19
  • 打赏
  • 举报
回复


*********************************************************************************/
/*
文件锁的使用。

*/
/********************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

void * fun(void * arg)
{
FILE *fp=(FILE*)arg;
char buf[10] = "hello!";
char buf2[10] = {'\0'};

printf("in pthread:%x %x\n", getpid(), pthread_self());

if (ftrylockfile(fp) != 0)
{
printf("flockfile error!\n");
}

flockfile(fp);

fwrite(buf, sizeof (char), 7, fp);
rewind(fp);
fread(buf2, sizeof(char), 6, fp);

fputs(buf2, stdout);
//funlockfile(fp);

fclose(fp);

return (void *)0;
}

int main()
{
pthread_t tid;
int err;
FILE *fp;
char buf[10] = "hello!";
char buf2[10] = {'\0'};

if ((fp = fopen("1.txt", "w+")) == NULL)
{
printf("open error!\n");
}

if ((err = pthread_create(&tid, NULL, fun, (void *)fp)) != 0)
{
printf("pthread error!\n");
fclose(fp);
}

if (ftrylockfile(fp) != 0)
{
printf("flockfile error!\n");
}

flockfile(fp);

fwrite(buf, sizeof (char), 7, fp);
rewind(fp);
fread(buf2, sizeof(char), 6, fp);

fputs(buf2, stdout);
//funlockfile(fp);

sleep(3); //如果主线程运行完了,子线程没运行完就结束了。

printf("in main:%x %x\n", getpid(), pthread_self());
printf("%d\n", pthread_equal(tid, pthread_self()));

fclose(fp);

return 0;
}

其他的异常处理的地方自己改改吧。
谭海燕 2011-08-18
  • 打赏
  • 举报
回复
锁,其实只是一种程序员之间的约定。比如你写一个接口,要求使用者必须加锁。。

树无影 2011-08-18
  • 打赏
  • 举报
回复
if (ftrylockfile(fp) != 0)
{
printf("flockfile error!\n");
}

这是判断啊?但是没效果啊?
wanchangjiu123 2011-08-18
  • 打赏
  • 举报
回复
文件锁是建议性锁 不是强制性锁

你这样用:

if(加锁成功){
你的操作;
解锁;
}
wanchangjiu123 2011-08-18
  • 打赏
  • 举报
回复
文件所是建议性的锁 不是强制性的锁

if(加锁成功){
你的操作;
解锁
}
树无影 2011-08-18
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 wanchangjiu123 的回复:]
我不理解你为了测试文件锁而代码这样写: 一个线程和一个主控线程 文件被打开两次 也就是说在同一个进程中 文件打开两次 你看我的测试代码 也许可以帮助你理解文件锁

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<fcntl.h>
#include<unistd.h>
……
[/Quote]运行你的程序,但是还是可以两次写啊?我改写你的方式变为父子进程同步进行,避免了一个进程结束自动释放了锁。但是结果还是错了。还是两个进程都可以写啊??

代码:

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/stat.h>
#include <signal.h>

#define MODE S_IRUSR|S_IWUSR

void out_file(int fd,char *s);

struct flock flockbuff;

static volatile int sigflag;
static sigset_t newmask, oldmask,zeromask;

static void sig_usr(int signo)
{
sigflag = 1;
}

void TELL_WAIT(void)
{
if (signal(SIGUSR1, sig_usr) == SIG_ERR)
{
printf("signal1 error!\n");
}

if (signal(SIGUSR2, sig_usr) == SIG_ERR)
{
printf("signal2 error!\n");
}

sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGUSR1);
sigaddset(&newmask, SIGUSR2);

if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
{
printf("sigprocmask error!");
}
}

void TELL_PARENT(pid_t pid)
{
kill(pid, SIGUSR2);
}

void TELL_CHILD(pid_t pid)
{
kill(pid, SIGUSR1);
}

void WAIT_PARENT( void )
{
while (sigflag == 0)
{
sigsuspend(&zeromask);
}

sigflag = 0;

if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
{
printf("SIG_SETMASK error!\n");
}
}

void WAIT_CHILD( void )
{
while (sigflag == 0)
{
sigsuspend(&zeromask);
}

sigflag = 0;

if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
{
printf("SIG_SETMASK error!\n");
}
}


int main(int argc,char *argv[])
{
int status;

if(argc < 2)
{
fprintf(stderr,"usage:%s file\n",argv[0]);
exit(1);
}
int fd = open(argv[1],O_CREAT|O_WRONLY,MODE);
if(fd<0)
{
fprintf(stderr,"open:%s\n",strerror(errno));
exit(1);
}

memset(&flockbuff,0,sizeof(flockbuff));
flockbuff.l_type = F_WRLCK;
flockbuff.l_start = 0;
flockbuff.l_whence = SEEK_SET;
flockbuff.l_len = 0;

TELL_WAIT();
pid_t pid = fork();

if(pid <0)
{
fprintf(stderr,"fork:%s\n",strerror(errno));
}
else if(pid > 0)
{
WAIT_CHILD();
char *d ="AAAAAAAAAA";
out_file(fd,d);
TELL_CHILD(pid);
WAIT_CHILD();
}
else if(pid == 0)
{
if(flockbuff.l_type == F_WRLCK)
{
printf("write\n");
}
char *d= "aaaaaaaaaa";
out_file(fd,d);
//sleep(10);
TELL_PARENT(getppid());
WAIT_PARENT();
TELL_PARENT(getppid());
}

}

void out_file(int fd,char *s)
{
int i = 0;
if(fcntl(fd,F_SETLKW,&flockbuff)<0)
{
fprintf(stderr,"fcntl:%s\n",strerror(errno));
exit(1);
}
for(;i<strlen(s);i++)
{
write(fd,s+i,sizeof(char));
//sleep(1);
}
close(fd);
}

运行结果:
[root@localhost work1]# gcc 1.c -o 1 -lpthread
[root@localhost work1]# ./1 7.txt
write
[root@localhost work1]# cat 7.txt
aaaaaaaaaaAAAAAAAAAA[root@localhost work1]#

看见没?都写进去了
wanchangjiu123 2011-08-18
  • 打赏
  • 举报
回复
我不理解你为了测试文件锁而代码这样写: 一个线程和一个主控线程 文件被打开两次 也就是说在同一个进程中 文件打开两次 你看我的测试代码 也许可以帮助你理解文件锁

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/stat.h>
#define MODE S_IRUSR|S_IWUSR

void out_file(int fd,char *s);

struct flock flockbuff;

int main(int argc,char *argv[])
{
if(argc < 2)
{
fprintf(stderr,"usage:%s file\n",argv[0]);
exit(1);
}
int fd = open(argv[1],O_CREAT|O_WRONLY,MODE);
if(fd<0)
{
fprintf(stderr,"open:%s\n",strerror(errno));
exit(1);
}
memset(&flockbuff,0,sizeof(flockbuff));
flockbuff.l_type = F_WRLCK;
flockbuff.l_start = 0;
flockbuff.l_whence = SEEK_SET;
flockbuff.l_len = 0;

pid_t pid = fork();

if(pid <0)
{
fprintf(stderr,"fork:%s\n",strerror(errno));
}
else if(pid > 0)
{
char *d ="AAAAAAAAAA";
out_file(fd,d);
}
else if(pid == 0)
{
if(flockbuff.l_type == F_WRLCK)
{
printf("write\n");
}
char *d= "aaaaaaaaaa";
out_file(fd,d);
}

}

void out_file(int fd,char *s)
{
int i = 0;
if(fcntl(fd,F_SETLKW,&flockbuff)<0)
{
fprintf(stderr,"fcntl:%s\n",strerror(errno));
exit(1);
}
for(;i<strlen(s);i++)
{
write(fd,s+i,sizeof(char));
sleep(1);
}
close(fd);
}
天亮后说晚安 2011-08-18
  • 打赏
  • 举报
回复
if(加锁成功){
你的操作;
解锁;
}

23,125

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧