哈工大操作系統(tǒng)實(shí)驗(yàn)(四)進(jìn)程同步

本次實(shí)驗(yàn)比較簡(jiǎn)單,相較于前幾屆需要在linux0.11 底下實(shí)現(xiàn)信號(hào)量,這次只需要在linux下寫(xiě)個(gè)利用信號(hào)量解決生產(chǎn)者消費(fèi)者問(wèn)題已經(jīng)很簡(jiǎn)單了.
實(shí)驗(yàn)要求:
在Ubuntu上編寫(xiě)應(yīng)用程序“pc.c”拗窃,解決經(jīng)典的生產(chǎn)者—消費(fèi)者問(wèn)題,完成下面的功能:

  1. 建立一個(gè)生產(chǎn)者進(jìn)程黎做,N個(gè)消費(fèi)者進(jìn)程(N>1);
  2. 用文件建立一個(gè)共享緩沖區(qū)松忍;
  3. 生產(chǎn)者進(jìn)程依次向緩沖區(qū)寫(xiě)入整數(shù)0,1,2,...,M蒸殿,M>=500;
  4. 消費(fèi)者進(jìn)程從緩沖區(qū)讀數(shù)鸣峭,每次讀一個(gè)宏所,并將讀出的數(shù)字從緩沖區(qū)刪除,然后將本進(jìn)程ID和數(shù)字輸出到標(biāo)準(zhǔn)輸出摊溶;
    緩沖區(qū)同時(shí)最多只能保存10個(gè)數(shù)爬骤。

要求用信號(hào)量來(lái)解決問(wèn)題:
pc.c中將會(huì)用到sem_open()、sem_close()莫换、sem_wait()和sem_post()等信號(hào)量相關(guān)的系統(tǒng)調(diào)用

要用到的函數(shù)說(shuō)明:

int fseek(FILE *stream, long offset, int fromwhere);
函數(shù)設(shè)置文件指針stream的位置霞玄。
如果執(zhí)行成功,stream將指向以fromwhere為基準(zhǔn)拉岁,偏移offset(指針偏移量)個(gè)字節(jié)的位置溃列,函數(shù)返回0。
如果執(zhí)行失敗(比如offset超過(guò)文件自身大小)膛薛,則不改變stream指向的位置,函數(shù)返回一個(gè)非0值补鼻。
size_t fread(void *buffer,size_t size,size_t count, FILE *stream );   
buffer   是讀取的數(shù)據(jù)存放的內(nèi)存的指針   
size     是每次讀取的字節(jié)數(shù)   
count    是讀取次數(shù)   
stream   是要讀取的文件的指針 
從一個(gè)文件流中讀數(shù)據(jù)哄啄,最多讀取count個(gè)元素雅任,每個(gè)元素size字節(jié),如果調(diào)用成功返回實(shí)際讀取到的元素個(gè)數(shù)咨跌,如果不成功或讀到文件末尾返回 0沪么。
size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
(1)buffer:是一個(gè)指針,對(duì)fwrite來(lái)說(shuō)锌半,是要獲取數(shù)據(jù)的地址禽车;
(2)size:要寫(xiě)入內(nèi)容的單字節(jié)數(shù);
(3)count:要進(jìn)行寫(xiě)入size字節(jié)的數(shù)據(jù)項(xiàng)的個(gè)數(shù)刊殉;
(4)stream:目標(biāo)文件指針殉摔;
(5)返回實(shí)際寫(xiě)入的數(shù)據(jù)項(xiàng)個(gè)數(shù)count。

思路:建立文件緩沖區(qū)
0-9位存生產(chǎn)的數(shù)據(jù),第10位存儲(chǔ)當(dāng)前讀到的位置.

消費(fèi)者讀取的位置的時(shí)候要執(zhí)行兩次,一次讀出當(dāng)前所讀位置,第二次根據(jù)此位置計(jì)算位偏移;


fseek( fp, 10*sizeof(int), SEEK_SET );
fread( &Outpos, sizeof(int), 1, fp);

fseek( fp, Outpos*sizeof(int), SEEK_SET );
fread( &costnum, sizeof(int), 1, fp);

下面是實(shí)驗(yàn)所需文件pc.c:

#define   __LIBRARY__
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>

#define ALLNUM 550
#define CUSTOMERNUM 5
#define BUFFERSIZE 10
void Producters(pid_t pid,FILE *fp);
void Customer(pid_t pid,FILE *fp);
sem_t *empty,*full,*mutex;
FILE *fp=NULL;
int Inpos=0;
int Outpos=0;


int main()
{
    int i,j,k;
    pid_t producter;
    pid_t customer;
    empty=(sem_t *)sem_open("empty",O_CREAT,0064,10);
    full=(sem_t *)sem_open("full",O_CREAT,0064,0);
    mutex=(sem_t*)sem_open("mutex",O_CREAT,0064,1);

//開(kāi)啟三個(gè)信號(hào)量
    fp=fopen("products.txt","wb+");
    fseek(fp,10*sizeof(int),SEEK_SET);
    fwrite(&Outpos,sizeof(int),1,fp);
    fflush(fp);
    producter=fork();
    if(producter==0)
    {
        Producters(producter,fp);
    }
    for (i=0;i<CUSTOMERNUM;i++)
    {

        customer=fork();
        if(customer==0)
        {
            Customer(customer,fp);
        }
    }
    wait(NULL);
    wait(NULL);
    wait(NULL);
    wait(NULL);
    wait(NULL);
    wait(NULL);
    //開(kāi)了6個(gè)進(jìn)程
    sem_unlink("empty");
    sem_unlink("full");
    sem_unlink("mutex");
    fclose(fp);
    return 0;
}
void Producters(pid_t pid,FILE *fp)
{
    int i=0;
    for (i=0;i<ALLNUM;i++)
    {
        sem_wait(empty);
        sem_wait(mutex);
        fseek( fp, Inpos * sizeof(int), SEEK_SET );
        fwrite(&i,sizeof(int),1,fp);
        fflush(fp);
        Inpos=(Inpos +1) % BUFFERSIZE;
        sem_post(mutex);
        sem_post(full);
    }
     return;
}

void Customer(pid_t pid,FILE *fp)
{
    int j,productid;
    for (j=0;j<ALLNUM/CUSTOMERNUM;j++)
    {
        sem_wait(full);
        sem_wait(mutex);
        fflush(stdout);
        fseek(fp,10*sizeof(int),SEEK_SET);
        fread(&Outpos,sizeof(int),1,fp);
        fseek(fp,Outpos*sizeof(int),SEEK_SET);
        fread(&productid,sizeof(int),1,fp);
        printf("%d:   %d\n",getpid(),productid);
        fflush(stdout);
        Outpos=(Outpos+1)% BUFFERSIZE;
        fseek(fp,10*sizeof(int),SEEK_SET);
        fwrite(&Outpos,sizeof(int),1,fp);
        fflush(fp);
        sem_post(mutex);
        sem_post(empty);
    }
    return;
}



報(bào)告:
(1)在pc.c中去掉所有與信號(hào)量有關(guān)的代碼记焊,再運(yùn)行程序逸月,執(zhí)行效果有變化嗎?為什么會(huì)這樣遍膜?
執(zhí)行結(jié)果Customer的消費(fèi)數(shù)據(jù)沒(méi)有按遞增的順序輸出,而且且fread()函數(shù)將產(chǎn)生錯(cuò)誤;
原因:
因?yàn)闆](méi)有信號(hào)量P(S)控制碗硬,導(dǎo)致生產(chǎn)者可能在緩沖區(qū)滿(mǎn)后繼續(xù)生產(chǎn),導(dǎo)致沒(méi)有被消費(fèi)的數(shù)據(jù)被覆蓋瓢颅,使得消費(fèi)者消費(fèi)的數(shù)據(jù)不是遞增序列恩尾。
同時(shí),沒(méi)有信號(hào)量V(S)控制挽懦,導(dǎo)致消費(fèi)者可能在讀取所有數(shù)據(jù)后仍然繼續(xù)讀取翰意,導(dǎo)致讀取的數(shù)據(jù)無(wú)效。
沒(méi)有mutex信號(hào)量控制導(dǎo)致出現(xiàn)多進(jìn)程并發(fā)訪問(wèn)緩沖區(qū)巾兆,導(dǎo)致出現(xiàn)fread()錯(cuò)誤猎物。
(2)實(shí)驗(yàn)的設(shè)計(jì)者在第一次編寫(xiě)生產(chǎn)者——消費(fèi)者程序的時(shí)候,是這么做的:
Producer()
{ P(Mutex); //互斥信號(hào)量
生產(chǎn)一個(gè)產(chǎn)品item;
P(Empty); //空閑緩存資源
將item放到空閑緩存中;
V(Full); //產(chǎn)品資源
V(Mutex);
}
Consumer()
{ P(Mutex);
P(Full);
從緩存區(qū)取出一個(gè)賦值給item;
V(Empty);
消費(fèi)產(chǎn)品item;
V(Mutex);
}
這樣可行嗎角塑?如果可行蔫磨,那么它和標(biāo)準(zhǔn)解法在執(zhí)行效果上會(huì)有什么不同?如果不可行圃伶,那么它有什么問(wèn)題使它不可行堤如?

這樣做不可行,只有當(dāng)緩沖區(qū)可寫(xiě)或者可讀時(shí)窒朋,才能鎖定該臨界資源搀罢,否則容易出現(xiàn)緩沖區(qū)未鎖定(mutex=1),consumer鎖定該緩沖區(qū)侥猩,卻發(fā)現(xiàn)empty=10榔至,full=0,等待緩沖區(qū)有字符信號(hào)量欺劳,這樣程序會(huì)進(jìn)入死鎖狀態(tài)唧取。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末铅鲤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子枫弟,更是在濱河造成了極大的恐慌邢享,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淡诗,死亡現(xiàn)場(chǎng)離奇詭異骇塘,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)韩容,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)款违,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人宙攻,你說(shuō)我怎么就攤上這事奠货。” “怎么了座掘?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵递惋,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我溢陪,道長(zhǎng)萍虽,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任形真,我火速辦了婚禮杉编,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘咆霜。我一直安慰自己邓馒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布蛾坯。 她就那樣靜靜地躺著光酣,像睡著了一般。 火紅的嫁衣襯著肌膚如雪脉课。 梳的紋絲不亂的頭發(fā)上救军,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音倘零,去河邊找鬼唱遭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛呈驶,可吹牛的內(nèi)容都是我干的拷泽。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼跌穗!你這毒婦竟也來(lái)了订晌?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蚌吸,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后砌庄,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體羹唠,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年娄昆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了佩微。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡萌焰,死狀恐怖哺眯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扒俯,我是刑警寧澤奶卓,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站撼玄,受9級(jí)特大地震影響夺姑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜掌猛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一盏浙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧荔茬,春花似錦废膘、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至坊萝,卻和暖如春孵稽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背十偶。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工菩鲜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人惦积。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓接校,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蛛勉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容