2014-10-02 38 views
0
#! /bin/sh 
    # count2 also increments and appends a value to the numbers file 
    # but only when it can successfully create a new hard link to the numbers file 

    count=0 
    while [ $count -lt 200 ]  # still loop 200 times 
    do 
     count=`expr $count + 1` # increment the loop counter 
     if ln numbers numbers.lock # try to enter the critical region 
     then      # in this case, ln is similar to TSL 
      n=`tail -1 numbers`  # get the last number to increment 
      expr $n + 1 >> numbers # increment it and append it to the file 
      rm numbers.lock   # exit the critical region 
     fi       # Note that if the ln was unsuccessful, we don't 
           # do busy waiting, but just continue looping 
    done 

我的任务是在c中实现下面的shellcript,但我知道如何实现“如果ln数字numbers.lock#尝试进入临界区域“ 在c。脚本的功能是将它计数到200个,并将其输出到一个文件中,计算1-200的数字......我知道该怎么做,但棘手的部分是运行实现这个功能的ac程序,但运行同一个实例该程序在同一时间多次。这意味着所有的程序都会尝试写入相同的文件,从而产生非常无序的输出,例如:1 1 1 2 2 2 3 3 3 3 4 4 4例如!解决方法是实现一个锁,以便访问资源的程序在完成执行之前不会受到干扰,完成后,下一个程序可以在“后台”运行时使用该资源。我该怎么做呢?或者我如何复制特定的代码行?任何有用的资源参考将不胜感激,我一直在寻找,但我最终在阅读复杂的东西在C,我没有在C编程经验。为了清楚地说明问题:如何实现那些锁定是我主要关心的锁定。谢谢!使用单个程序在c中写入一个空文件,但同时运行它不止一次

回答

1

在这段代码中,通过创建一个硬链接(可以假定为原子)来实现互斥性。如果你想用C来模仿,你可能想看看POSIX函数link(2)

返回值-1表示失败。然而,即使脚本没有这样做,最好也检查errno以查看失败是否真的是由已经存在的链接引起的(例如,程序的另一个实例在关键部分中,由errno == EEXIST),以防止其他错误(例如,只读文件系统)的无限循环。

并且为了在退出临界区时删除该链接,unlink(2)是您的朋友。

0

一个简单而恰当的方式将是你的C代码写这篇文章:

int result = system("ln numbers numbers.lock") 

如果返回值是0,那么它成功地创建链接,这意味着它已经收购了锁你的方案。

或者,您可能会考虑不使用符号链接作为锁,而是使用flock system call来代替。它的工作方式是在C程序中打开文件,然后调用flock来锁定它。

+1

3备注:1)LN默认创建硬链接,而不是符号链接(LN -s创建符号链接)2)使用链路系统调用由@misberner的建议比炮击了少了很多重手和3)flock确实是一个非常不错的选择,如果解决方案应该在具有较旧Linux内核的共享(nfs)文件系统上工作,请谨慎行事。 – fvu 2014-10-02 00:28:18

+0

谢谢,我会修复地址#1的答案。 – 2014-10-02 06:06:29

0

这里是linux下c下的小群集实现。解释在代码注释中给出。 也有关OS的更多信息,我推荐着名的APUE书。

#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <string.h> 

#define LOCK_FILE "lock.txt" 

void error_fatal (const char *message){ 
    perror (message); 
    exit (EXIT_FAILURE); 
} 

/* we demonstrate file locking. (Mandatory locking) */ 

int main(){ 
    int fd,i; 
    char str[10]; 
    struct flock lock; 

    /* Open the file. (fd is file-descriptor) */ 
    if ((fd = open (LOCK_FILE, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) 
    error_fatal ("open error"); 

    /* Here we initialize lock values based on our usecase 
    in our case we want write lock and we want lock to cover whole file. 
    (file region) */ 
    lock.l_type = F_WRLCK; 
    lock.l_whence = SEEK_SET; 
    lock.l_start = 0; 
    lock.l_len = 0; 

    /* We try to set the lock */ 
    if (fcntl (fd, F_SETLK, &lock) < 0){ 

    /* Case when there is another instance already running */ 
    if (errno == EACCES || errno == EAGAIN){ 
     printf ("Another instance already running.\n"); 
     exit (EXIT_SUCCESS); 
    } 
    else 
     error_fatal ("fcntl error"); 
    } 


    /* Write numbers from 1 to 10 for demonstration. */ 
    for(i = 1; i <= 10; i++) { 
    sprintf(str, "%d", i); 
    write(fd, str, strlen(str)); 
    /* After each write, sleep */ 
    sleep(1); 
    } 

    /* This program is set to sleep after each write (i sec) and in this timeframe we should execute another instance of program to see if locking is successful. 

    Check lock.txt file to see number ordering. 

    */ 


    return 0; 
} 
相关问题