2014-10-02 34 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; 
} 
相關問題