鱼C论坛

 找回密码
 立即注册
查看: 3851|回复: 11

[已解决]为什么先加读锁再加写锁不可以?

[复制链接]
发表于 2021-10-11 16:39:13 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x

                               
登录/注册后可看大图
最佳答案
2021-10-12 23:23:55
好了,我的基础知识补充的差不多了,开始回答你的问题
为什么先加读锁再加写锁不可以?
这是规定了的,规定了不可以
读锁 锁的是其他进程的 写锁
写锁 锁的是其他进程的 读锁 和 写锁
原文是这么说的
       When a shared lock is set on a segment of a file, other processes shall be able to set shared locks on that segment or a portion of  it.  A
       shared  lock  prevents  any  other process from setting an exclusive lock on any portion of the protected area. A request for a shared lock
       shall fail if the file descriptor was not opened with read access.

下面是谷歌翻译的
当在文件的一个段上设置共享锁时,其他进程应该能够在该段或它的一部分上设置共享锁。 共享锁可防止任何其他进程在受保护区域的任何部分设置排他锁。 如果文件描述符不是用读访问打开的,则对共享锁的请求将失败。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-10-12 18:08:36 | 显示全部楼层
这个问题很简单,因为我看不到你的代码,所以不知道为什么
你看,简单吧

为什么别人不理你,不回复你的这个问题?问题出在自己身上
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-12 18:18:16 | 显示全部楼层
发代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-12 18:28:21 | 显示全部楼层


                               
登录/注册后可看大图

                               
登录/注册后可看大图

                               
登录/注册后可看大图

                               
登录/注册后可看大图
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-12 18:32:01 | 显示全部楼层

这也是别人不理你的原因之一,你发图片,别人就要照着图片抄代码,你发文本,别人就可以直接复制代码,你觉得别人会选择照着图片抄代码吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-12 18:41:07 | 显示全部楼层
人造人 发表于 2021-10-12 18:32
这也是别人不理你的原因之一,你发图片,别人就要照着图片抄代码,你发文本,别人就可以直接复制代码,你 ...
/* lock_set.c �ú������ã���fd�ļ�����������Ӧ���ļ���type���͵���(������������д�������) */

int lock_set(int fd, int type)
{
        struct flock old_lock, lock;
        lock.l_whence = SEEK_SET;/* �ļ���дָ����ʼλ�����ļ���ͷ */
        lock.l_start = 0;        /*���λ���������������ļ�??*/
        lock.l_len = 0;          /*�������򳤶ȣ����������ļ�*/
        lock.l_type = type;      /*type������������д���ͽ����������ͣ���Ψһ��Ҫ��ֵ��������l_type��ֵ�ļ���*/
        lock.l_pid = -1;         /*���ļ�ӵ���ļ����Ľ��̺ţ�Ĭ��Ϊ-1*/        
        
        fcntl(fd, F_GETLK, &lock);/* �ж��ļ��Ƿ�������� */
                                  /*F_GETLK:����lock����ֵ�������Ƿ�������ֻ�д��ڽ���״̬����������*/
                                  /*&lock:ȡflock�ṹ�����lock���׵�ַ*/
        
        /*�˴���fcntl()����ֻ��Ϊ�˲���fd�Ƿ�����������Ϊֻ���ļ�Ϊ����(������)״̬��������������ļ��Ѿ�������
          ����F_GETLK������Ҫ������жϣ�
          ���֮ǰ�Ѿ����ڵ��Ƕ����򻹿����϶����������д�������϶�����д����

          Ҳ����˵��Ҫ��һ��û�������ļ�����Ҫִ������fcntl()������
          ��һ��ִ�У�F_GETLK�������ļ�����Ϊ����״̬��fcntl()��������-1�����ĺ��徭�����Ը��ļ�����������
          �ڶ���fcntl()����ִ�оͿ��Է��Ĵ󵨵�������fcntl()�����᷵��0�������ɹ�*/
 

        
        if (lock.l_type != F_UNLCK)/*���lock.l_type���ǽ���״̬����ζ���Ѿ�����������*/
        {
                /* �ж��ļ�����������ԭ�� */
                if (lock.l_type == F_RDLCK) /* ���ļ����ж��� */
                {
                        printf("Read lock already set by process PID:%d\n", lock.l_pid);
                }
                else if (lock.l_type == F_WRLCK) /* ���ļ�����д�� */
                {
                        printf("Write lock already set by process PID:%d\n", lock.l_pid);
                }                        
        }

               
        
        lock.l_type = type;/* l_type �����ѱ�F_GETLK�޸Ĺ���������Ҫ���¸�ֵ*/
        
/* ���ݲ�ͬ��typeֵ��������ʽ�������������ν����ʽ����ζ�����û�гɹ������������׽���źţ������һֱ��������״̬ */
        if ((fcntl(fd, F_SETLKW, &lock)) < 0) 
                      /*F_SETLKW�����޷���ȡ��ʱ,����˯�ߣ�����ɻ������׽���źţ��򷵻�*/
                      /*&lock:ȡflock�ṹ�����lock���׵�ַ*/

         /*�˴�fcntl()�������ã���fd�ļ�����������Ӧ���ļ���lock�ṹ�������ȷ����l_type���͵�����
                                ��ʱ��F_GETLKWֱ�Ӹ��ļ����ļ�������Ϊ��һ��fcntl()�����Ѿ����Թ�
                                ���ļ��������������DZ���fcntl()�������Գɹ�ִ�У�������0 */

        {
                printf("Lock failed:type = %d\n", lock.l_type);
                return 1;
        }
                
        switch(lock.l_type)
        {
                case F_RDLCK:
                {
                        printf("Read lock set by process PID:%d\n", getpid());/*���ļ��ѱ�getpid()�������˶���*/
                }
                break;

                case F_WRLCK:
                {
                        printf("Write lock set by process PID:%d\n", getpid());/*���ļ��ѱ�getpid()��������д��*/
                }
                break;

                case F_UNLCK:
                {
                        printf("Release lock by process PID:%d\n", getpid());/*���ļ��ѱ�getpid()���̽���*/
                        return 1;
                }
                break;

                default:
                break;
        }/* end of switch  */
        
        return 0;
}

/* read_lock.c */

#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include "lock_set.c"

int main(void)
{
        int fd;
        
        fd = open("hello",O_RDWR | O_CREAT, 0644);
        if(fd < 0)
        {
                printf("Open file error\n");
                exit(1);
        }        
        
        lock_set(fd, F_RDLCK);/* ���ļ��϶�ȡ��������������ڵȴ����������ַ��ĵȴ�״̬�� */

        getchar();/*ȡ���̼�����ַ��������ó������ִ����ȥ*/        
        
        lock_set(fd, F_UNLCK);/* ���ļ����� */

        getchar();
        
        close(fd);
        exit(0);
}
/* write_lock.c */
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include "lock_set.c"

int main(void)
{
        int fd;        
        
        fd = open("hello",O_RDWR | O_CREAT, 0644);/* ���ȴ��ļ� */
        if(fd < 0)
        {
                printf("Open file error\n");
                exit(1);
        }        
        
        lock_set(fd, F_WRLCK);/* ���ļ���д���� */
        getchar();        
        
        lock_set(fd, F_UNLCK);/* ���ļ����� */
        getchar();
        
        close(fd);
        
        exit(0);
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-12 18:56:45 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-12 18:57:16 | 显示全部楼层
改成 utf-8 格式看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-12 19:32:38 | 显示全部楼层
人造人 发表于 2021-10-12 18:57
改成 utf-8 格式看看
/* lock_set.c 该函数作用:给fd文件描述符所对应的文件上type类型的锁(包括:读锁、写锁或解锁) */

int lock_set(int fd, int type)
{
        struct flock old_lock, lock;
        lock.l_whence = SEEK_SET;/* 文件读写指针起始位置在文件开头 */
        lock.l_start = 0;        /*相对位移量;加锁整个文件??*/
        lock.l_len = 0;          /*加锁区域长度;加锁整个文件*/
        lock.l_type = type;      /*type包含:读锁、写锁和解锁三个类型;给唯一需要赋值的锁类型l_type赋值文件锁*/
        lock.l_pid = -1;         /*该文件拥有文件锁的进程号,默认为-1*/        
        
        fcntl(fd, F_GETLK, &lock);/* 判断文件是否可以上锁 */
                                  /*F_GETLK:根据lock参数值,决定是否上锁;只有处于解锁状态,才能上锁*/
                                  /*&lock:取flock结构体变量lock的首地址*/
        
        /*此处的fcntl()函数只是为了测试fd是否能上锁,因为只有文件为解锁(不上锁)状态才能上锁;如果文件已经上锁,
          根据F_GETLK参数就要看情况判断:
          如果之前已经存在的是读锁则还可以上读锁,如果是写锁则不能上读锁或写锁;

          也就是说:要给一个没上锁的文件上锁要执行两次fcntl()函数;
          第一次执行:F_GETLK参数将文件设置为解锁状态;fcntl()函数返回-1,表达的含义经过测试该文件可以上锁;
          第二次fcntl()函数执行就可以放心大胆的上锁,fcntl()函数会返回0,上锁成功*/
 

        
        if (lock.l_type != F_UNLCK)/*如果lock.l_type不是解锁状态,意味着已经存在其他锁*/
        {
                /* 判断文件不能上锁的原因 */
                if (lock.l_type == F_RDLCK) /* 该文件已有读锁 */
                {
                        printf("Read lock already set by process PID:%d\n", lock.l_pid);
                }
                else if (lock.l_type == F_WRLCK) /* 该文件已有写锁 */
                {
                        printf("Write lock already set by process PID:%d\n", lock.l_pid);
                }                        
        }

               
        
        lock.l_type = type;/* l_type 可能已被F_GETLK修改过,所以需要重新赋值*/
        
/* 根据不同的type值进行阻塞式上锁或解锁,所谓阻塞式:意味着如果没有成功上锁或解锁或捕捉到信号,则程序一直处于阻塞状态 */
        if ((fcntl(fd, F_SETLKW, &lock)) < 0) 
                      /*F_SETLKW:在无法获取锁时,进入睡眠;如果可获得锁或捕捉到信号,则返回*/
                      /*&lock:取flock结构体变量lock的首地址*/

         /*此处fcntl()函数作用:给fd文件描述符所对应的文件上lock结构体变量所确定的l_type类型的锁;
                                此时用F_GETLKW直接给文件上文件锁,因为第一次fcntl()函数已经测试过
                                该文件可以上锁,于是本次fcntl()函数可以成功执行,并返回0 */

        {
                printf("Lock failed:type = %d\n", lock.l_type);
                return 1;
        }
                
        switch(lock.l_type)
        {
                case F_RDLCK:
                {
                        printf("Read lock set by process PID:%d\n", getpid());/*该文件已被getpid()进程上了读锁*/
                }
                break;

                case F_WRLCK:
                {
                        printf("Write lock set by process PID:%d\n", getpid());/*该文件已被getpid()进程上了写锁*/
                }
                break;

                case F_UNLCK:
                {
                        printf("Release lock by process PID:%d\n", getpid());/*该文件已被getpid()进程解锁*/
                        return 1;
                }
                break;

                default:
                break;
        }/* end of switch  */
        
        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-12 19:33:10 | 显示全部楼层
人造人 发表于 2021-10-12 18:57
改成 utf-8 格式看看
/* read_lock.c */

#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include "lock_set.c"

int main(void)
{
        int fd;
        
        fd = open("hello",O_RDWR | O_CREAT, 0644);
        if(fd < 0)
        {
                printf("Open file error\n");
                exit(1);
        }        
        
        lock_set(fd, F_RDLCK);/* 给文件上读取锁,上锁后程序处于等待键盘输入字符的等待状态; */

        getchar();/*取键盘键入的字符,可以让程序继续执行下去*/        
        
        lock_set(fd, F_UNLCK);/* 给文件解锁 */

        getchar();
        
        close(fd);
        exit(0);
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-10-12 19:33:40 | 显示全部楼层
人造人 发表于 2021-10-12 18:57
改成 utf-8 格式看看
/* write_lock.c */
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include "lock_set.c"

int main(void)
{
        int fd;        
        
        fd = open("hello",O_RDWR | O_CREAT, 0644);/* 首先打开文件 */
        if(fd < 0)
        {
                printf("Open file error\n");
                exit(1);
        }        
        
        lock_set(fd, F_WRLCK);/* 给文件上写入锁 */
        getchar();        
        
        lock_set(fd, F_UNLCK);/* 给文件解锁 */
        getchar();
        
        close(fd);
        
        exit(0);
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-10-12 23:23:55 | 显示全部楼层    本楼为最佳答案   
好了,我的基础知识补充的差不多了,开始回答你的问题
为什么先加读锁再加写锁不可以?
这是规定了的,规定了不可以
读锁 锁的是其他进程的 写锁
写锁 锁的是其他进程的 读锁 和 写锁
原文是这么说的
       When a shared lock is set on a segment of a file, other processes shall be able to set shared locks on that segment or a portion of  it.  A
       shared  lock  prevents  any  other process from setting an exclusive lock on any portion of the protected area. A request for a shared lock
       shall fail if the file descriptor was not opened with read access.

下面是谷歌翻译的
当在文件的一个段上设置共享锁时,其他进程应该能够在该段或它的一部分上设置共享锁。 共享锁可防止任何其他进程在受保护区域的任何部分设置排他锁。 如果文件描述符不是用读访问打开的,则对共享锁的请求将失败。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-22 04:11

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表