竞争原则(racing)

我们的率先个例证是四个经过写文件的例证,纵然还未有做到通讯,可是这正如便于的证雅培个通讯时通常现身的状态:竞争原则。假诺大家要并发玖21个进程,那几个进度约定好二个文书,那个文件带头值内容写0,每叁个进程都要张开那些文件读出方今的数字,加一今后将结果写回去。在能够图景下,那一个文件最终写的数字应该是100,因为有玖拾九个经过展开、读数、加1、写回,自然是某些许个进度最后文件中的数字结果就应当是某些。然则其实并不是那样,可以看一下以此例子:

[zorro@zorrozou-pc0 process]$ cat racing.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/file.h>
#include <wait.h>

#define COUNT 100
#define NUM 64
#define FILEPATH "/tmp/count"

int do_child(const char *path)
{
    /* 这个函数是每个子进程要做的事情
    每个子进程都会按照这个步骤进行操作:
    1. 打开FILEPATH路径的文件
    2. 读出文件中的当前数字
    3. 将字符串转成整数
    4. 整数自增加1
    5. 将证书转成字符串
    6. lseek调整文件当前的偏移量到文件头
    7. 将字符串写会文件
    当多个进程同时执行这个过程的时候,就会出现racing:竞争条件,
    多个进程可能同时从文件独到同一个数字,并且分别对同一个数字加1并写回,
    导致多次写回的结果并不是我们最终想要的累积结果。 */
    int fd;
    int ret, count;
    char buf[NUM];
    fd = open(path, O_RDWR);
    if (fd < 0) {
        perror("open()");
        exit(1);
    }
    /*  */
    ret = read(fd, buf, NUM);
    if (ret < 0) {
        perror("read()");
        exit(1);
    }
    buf[ret] = '\0';
    count = atoi(buf);
    ++count;
    sprintf(buf, "%d", count);
    lseek(fd, 0, SEEK_SET);
    ret = write(fd, buf, strlen(buf));
    /*  */
    close(fd);
    exit(0);
}

int main()
{
    pid_t pid;
    int count;

    for (count=0;count<COUNT;count++) {
        pid = fork();
        if (pid < 0) {
            perror("fork()");
            exit(1);
        }

        if (pid == 0) {
            do_child(FILEPATH);
        }
    }

    for (count=0;count<COUNT;count++) {
        wait(NULL);
    }
}

以此顺序做后施行的成效如下:

[zorro@zorrozou-pc0 process]$ make racing
cc     racing.c   -o racing
[zorro@zorrozou-pc0 process]$ echo 0 > /tmp/count
[zorro@zorrozou-pc0 process]$ ./racing 
[zorro@zorrozou-pc0 process]$ cat /tmp/count 
71[zorro@zorrozou-pc0 process]$ 
[zorro@zorrozou-pc0 process]$ echo 0 > /tmp/count
[zorro@zorrozou-pc0 process]$ ./racing 
[zorro@zorrozou-pc0 process]$ cat /tmp/count 
61[zorro@zorrozou-pc0 process]$ 
[zorro@zorrozou-pc0 process]$ echo 0 > /tmp/count
[zorro@zorrozou-pc0 process]$ ./racing 
[zorro@zorrozou-pc0 process]$ cat /tmp/count 
64[zorro@zorrozou-pc0 process]$

大家试行了三回那一个顺序,每趟结果都不太相通,第一回是71,第一遍是61,首次是64,全都未有赢得预期结果,这就是竞争原则(racing卡塔尔引进的主题材料。稳重解析那么些进程大家可以开采这些角逐原则是什么样爆发的:

最开始文件内容是0,假诺那时同时开拓了3个经过,那么她们各自读文件的时候,那么些进程是或然现身的,于是各个进程读到的数组或者都以0,因为他俩都在其余进程没写入1事情发生前就带头读了文本。于是多个进度都是给0加1,然后写了个1回到文件。其余进度就那样类推,每一次玖拾八个进度的施行各样可能分裂,于是结果是每一回获得的值都可能不太相通,不过无可批驳都有限产生的骨子里进度个数。于是大家把这种多少个实践进程(如进度或线程)中访谈同贰个分享财富,而那些分享能源又有敬敏不谢被八个实行进程存取的的程序片段,叫做临界区代码。

那正是说该怎么着解决这几个racing的主题素材吗?对于那个例子来讲,可以用文件锁的主意缓慢解决那个主题材料。便是说,对临界区代码进行加锁,来消除竞争条件的题目。哪段是临界区代码?在这里个事例中,两端/
/之间的有的就是临界区代码。二个不易的例子是:

...
    ret = flock(fd, LOCK_EX);
    if (ret == -1) {
        perror("flock()");
        exit(1);
    }

    ret = read(fd, buf, NUM);
    if (ret < 0) {
        perror("read()");
        exit(1);
    }
    buf[ret] = '\0';
    count = atoi(buf);
    ++count;
    sprintf(buf, "%d", count);
    lseek(fd, 0, SEEK_SET);
    ret = write(fd, buf, strlen(buf));
    ret = flock(fd, LOCK_UN);
    if (ret == -1) {
        perror("flock()");
        exit(1);
    }
...

大家将临界区部分代码前后都使用了flock的互斥锁,幸免了临界区的racing。那一个例子即使并从未真的达到让三个进程经过文件进行通讯,化解某种协作专门的学问难点的目标,但是能够展现出进度间通讯机制的局地难点了。当提到到数量在多个经过间开展分享的时候,仅仅只兑现数据通讯或分享机制自己是相当不足的,还必要得以达成相关的一块或异步机制来决定几个经过,达到维护临界区或任何让进程能够拍卖一齐或异步事件的力量。我们得以感到文件锁是能够完成那样一种多进度的调弄收拾协同本事的编写制定,而除去文件锁以外,还恐怕有任何机制得以高达相似可能差异的效劳,大家会在下文中继续详细分解。

重复,咱们并不对flock那几个办法本人进行功用性疏解。这种功效性解说我们能够很随便的在互连网也许经过别的书籍得到有关内容。本文特别讲究的是Linux蒙受提供了有些种文件锁以致她们的区分是哪些?

3.三种锁的涉及

那便是说flock和lockf/fcntl所上的锁有何关联吗?答案时互不影响。测验程序如下:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
int main(int argc, char **argv)
{
int fd, ret;
int pid;
fd = open("./tmp.txt", O_RDWR);
ret = flock(fd, LOCK_EX);
printf("flock return ret : %d\n", ret);
ret = lockf(fd, F_LOCK, 0);
printf("lockf return ret: %d\n", ret);
sleep(100);
return 0;
}

测量试验结果如下:

$./a.out

flockreturnret:0

lockfreturnret:0

可以预知flock的加锁,并不影响lockf的加锁。两外我们能够通过/proc/locks查看进程得到锁的情事。

$psaux|grepa.out|grep-vgrep

123751188490.00.011904440pts/5S+01:090:00./a.out

$sudocat/proc/locks|grep18849

1:POSIXADVISORYWRITE1884908:02:8526740EOF

2:FLOCKADVISORYWRITE1884908:02:8526740EOF

大家能够见见/proc/locks下边有锁的音讯:小编后天各自陈说下含义:

1卡塔尔(قطر‎POSIXFLOCK这些比较显然,便是哪个项目标锁。flock系统调用产生的是FLOCK,fcntl调用F_SETLK,F_SETLKW大概lockf发生的是POSIX类型,有次可以见到二种调用发生的锁的类型是差异的;

2卡塔尔国ADVISORAV4Y声明是劝告锁;

3卡塔尔(قطر‎W宝马7系ITE一面之识,是写锁,还会有读锁;

4卡塔尔(قطر‎18849是全数锁的经过ID。当然对于flock那种类型的锁,会现出进度一度淡出的面貌。

5卡塔尔(قطر‎08:02:852674象征的对应磁盘文件的所在设备的主设备好,次设备号,还应该有文件对应的inodenumber。

6卡塔尔国0象征的是所的实际上地点

金沙糖果派对网站app,7卡塔尔EOF表示的是终止地方。那四个字段对fcntl类型相比较有用,对flock来是总是0和EOF。

fcntl(卡塔尔国、lockf、flock的分别 ——lvyilong316
那八个函数的功力都是给文件加锁,这它们有啥样界别吧?首先floc…

前言

动用文件实行进程间通讯应该是初次学会的一种IPC模式。任何编程语言中,文件IO都是很器重的学识,所以接纳文件举办进度间通讯就成了很自然被学会的一种花招。思忖到系统对文件本人存在缓存机制,使用文件举行IPC的频率在好几多读少写的地方下并不放下。但是我们就好像平日忘记IPC的体制得以归纳“文件”这一选项。

金沙糖果派对2015cc,大家首先引进文件进行IPC,试图先利用文件实行通讯引进二个竞争原则的概念,然后选拔文件锁消逝那些主题素材,进而先从文件的角度来以点带面的看一下世袭相关IPC机制的全体要缓慢解决的主题素材。阅读本文能够帮您解决以下难点:

  1. 怎么样是竞争原则(racing)?。
  2. flock和lockf有啥样分裂?
  3. flockfile函数和flock与lockf有啥差别?
  4. 哪些使用命令查看文件锁?

linux中fcntl()、lockf、flock的区别

fcntl()、lockf、flock的区别
——lvyilong316

这两个函数的意义都以给文件加锁,这它们有哪些界别吧?首先flock和fcntl是系统调用,而lockf是库函数。lockf实际上是fcntl的包装,所以lockf和fcntl的尾部达成是一致的,对文本加锁的成效也是同等的。前边深入分析不一样点时大好多情景是将fcntl和lockf放在一同的。上边首先看各种函数的运用,从利用的点子和功能来看各种函数的分别。

admin

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注