亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫(kù)
最近訪問(wèn)板塊 發(fā)新帖
查看: 2154 | 回復(fù): 0
打印 上一主題 下一主題

UNIX/LINUX 多線程編程快速撐握 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2006-03-23 18:54 |只看該作者 |倒序?yàn)g覽
                        多線程編程快速撐握
        
=============================================         
原文出自:
http://atg.cublog.cn/
     作者: 董 暉  2006-03-05
注: 轉(zhuǎn)載請(qǐng)注明原文出處
最近在unix sco 下搞多線程編程, 開(kāi)始也摸不著頭腦, 經(jīng)過(guò)幾天的周折總算是搞出來(lái)了!
如果您想了解多線程編程那你找對(duì)文章了!!!
但如果您是這方面的專家,那希望您花一點(diǎn)寶貴的時(shí)間讀完本文! 把我寫(xiě)得不對(duì)與不足的地方
指出來(lái)! Email:
atgjplh@126.com
1. 線程
    線程通常叫做輕型的進(jìn)程。雖然這個(gè)叫法有些簡(jiǎn)單化,但這有利于了解線程的概念。
因?yàn)榫程和進(jìn)程比起來(lái)很小,所以相對(duì)來(lái)說(shuō),線程花費(fèi)更少的CPU資源。進(jìn)程往往需要它們自己的資源,
但線程之間可以共享資源,所以線程更加節(jié)省內(nèi)存。Mach的線程使得程序員可以編寫(xiě)并發(fā)運(yùn)行的程序,
而這些程序既可以運(yùn)行在單處理器的機(jī)器上,也可以運(yùn)行在多處理器的機(jī)器中。另外,在單處理器環(huán)境中,
當(dāng)應(yīng)用程序執(zhí)行容易引起阻塞和延遲的操作時(shí),線程可以提高效率。
    使用多線程的理由之一是和進(jìn)程相比,它是一種非常"節(jié)儉"的多任務(wù)操作方式。我們知道,在Linux系統(tǒng)下,
啟動(dòng)一個(gè)新的進(jìn)程必須分配給它獨(dú)立的地址空間,建立眾多的數(shù)據(jù)表來(lái)維護(hù)它的代碼段、堆棧段和數(shù)據(jù)段,
這是一種"昂貴"的多任務(wù)工作方式。而運(yùn)行于一個(gè)進(jìn)程中的多個(gè)線程,它們彼此之間使用相同的地址空間,
共享大部分?jǐn)?shù)據(jù),啟動(dòng)一個(gè)線程所花費(fèi)的空間遠(yuǎn)遠(yuǎn)小于啟動(dòng)一個(gè)進(jìn)程所花費(fèi)的空間,而且,
線程間彼此切換所需的時(shí)間也遠(yuǎn)遠(yuǎn)小于進(jìn)程間切換所需要的時(shí)間。據(jù)統(tǒng)計(jì),總的說(shuō)來(lái),一個(gè)進(jìn)程的開(kāi)銷大約是一
個(gè)線程開(kāi)銷的30倍左右,當(dāng)然,在具體的系統(tǒng)上,這個(gè)數(shù)據(jù)可能會(huì)有較大的區(qū)別。
  使用多線程的理由之二是線程間方便的通信機(jī)制。對(duì)不同進(jìn)程來(lái)說(shuō),它們具有獨(dú)立的數(shù)據(jù)空間,
要進(jìn)行數(shù)據(jù)的傳遞只能通過(guò)通信的方式進(jìn)行,這種方式不僅費(fèi)時(shí),而且很不方便。線程則不然,
由于同一進(jìn)程下的線程之間共享數(shù)據(jù)空間,所以一個(gè)線程的數(shù)據(jù)可以直接為其它線程所用,這不僅快捷,而且方便。
當(dāng)然,數(shù)據(jù)的共享也帶來(lái)其他一些問(wèn)題,有的變量不能同時(shí)被兩個(gè)線程所修改,有的子程序中聲明為static
的數(shù)據(jù)更有可能給多線程程序帶來(lái)災(zāi)難性的打擊,這些正是編寫(xiě)多線程程序時(shí)最需要注意的地方。
  除了以上所說(shuō)的優(yōu)點(diǎn)外,不和進(jìn)程比較,多線程程序作為一種多任務(wù)、并發(fā)的工作方式,當(dāng)然有以下的優(yōu)點(diǎn):
  1) 提高應(yīng)用程序響應(yīng)。這對(duì)圖形界面的程序尤其有意義,當(dāng)一個(gè)操作耗時(shí)很長(zhǎng)時(shí),整個(gè)系統(tǒng)都會(huì)等待這個(gè)操作,
        此時(shí)程序不會(huì)響應(yīng)鍵盤(pán)、鼠標(biāo)、菜單的操作,而使用多線程技術(shù),將耗時(shí)長(zhǎng)的操作(time consuming)置于一個(gè)新的線程,
        可以避免這種尷尬的情況。
  2) 使多CPU系統(tǒng)更加有效。操作系統(tǒng)會(huì)保證當(dāng)線程數(shù)不大于CPU數(shù)目時(shí),不同的線程運(yùn)行于不同的CPU上。
  3) 改善程序結(jié)構(gòu)。一個(gè)既長(zhǎng)又復(fù)雜的進(jìn)程可以考慮分為多個(gè)線程,成為幾個(gè)獨(dú)立或半獨(dú)立的運(yùn)行部分,
        這樣的程序會(huì)利于理解和修改。
2. 線程編程介紹
    用子函數(shù)pthread_create創(chuàng)建一個(gè)新的線程。它有四個(gè)參數(shù):一個(gè)用來(lái)保存線程的線程變量、一個(gè)線程屬性、
    當(dāng)線程執(zhí)行時(shí)要調(diào)用的函數(shù)和一個(gè)此函數(shù)的參數(shù)。
    例如:
    pthread_ta_thread ;
    pthread_attr_ta_thread_attribute ;
    void thread_function(void *argument);
    char * some_argument;
    pthread_create( &a_thread, a_thread_attribute, (void *)&thread_function,
    (void *) &some_argument);
    線程屬性只指明了需要使用的最小的堆棧大小。在以后的程序中,線程的屬性可以指定其他的值,
    但現(xiàn)在大部分的程序可以使用缺省值。不像UNIX系統(tǒng)中使用fork系統(tǒng)調(diào)用創(chuàng)建的進(jìn)程,它們和它們的父進(jìn)程使用同一個(gè)執(zhí)行點(diǎn),
    線程使用在pthread_create中的參數(shù)指明要開(kāi)始執(zhí)行的函數(shù)。
    現(xiàn)在我們可以編制第一個(gè)程序了。我們編制一個(gè)多線程的應(yīng)用程序,在標(biāo)準(zhǔn)輸出中打印“Hello Wo r l d”。
    首先我們需要兩個(gè)線程變量,一個(gè)新線程開(kāi)始執(zhí)行時(shí)可以調(diào)用的函數(shù)。我們還需要指明每一個(gè)線程應(yīng)該打印的信息。
    一個(gè)做法是把要打印的字符串分開(kāi),給每一個(gè)線程一個(gè)字符串作為開(kāi)始的參數(shù)。
    請(qǐng)看下面的代碼:
    void print_message_function( void *ptr );
    main( )
    {
    pthread_t thread1, thread2;
    char *message1 = "Hello";
    char *message2 = "Wo r l d " ;
    pthread_create( &thread1, pthread_attr_default,
    (void*)&print_message_function, (void*) message1);
    pthread_create(&thread2, pthread_attr_default,
    (void*)&print_message_function, (void*) message2);
    exit( 0 ) ;
    }
    void print_message_function( void *ptr )
    {
    char *message;
    message = (char *) ptr;
    printf("%s ", message);
    }
    程序通過(guò)調(diào)用pthread_create創(chuàng)建第一個(gè)線程,并將“Hello”作為它的啟動(dòng)參數(shù)。第二個(gè)線程的參數(shù)是“World”。
    當(dāng)?shù)谝粋(gè)線程開(kāi)始執(zhí)行時(shí),它使用參數(shù)“Hello”執(zhí)行函數(shù)print_message_function。它在標(biāo)準(zhǔn)輸出中打印“Hello”,
    然后結(jié)束對(duì)函數(shù)的調(diào)用。線程當(dāng)離開(kāi)它的初始化函數(shù)時(shí)就將終止,所以第一個(gè)線程在打印完“Hello”后終止。
    當(dāng)?shù)诙䝼(gè)線程執(zhí)行時(shí),它打印“World”然后終止。但這個(gè)程序有兩個(gè)主要的缺陷。
    首先也是最重要的是線程是同時(shí)執(zhí)行的。這樣就無(wú)法保證第一個(gè)線程先執(zhí)行打印語(yǔ)句。所以你很可能在屏幕上看到“World Hello”,
    而不是“Hello World”。請(qǐng)注意對(duì)exit的調(diào)用是父線程在主程序中使用的。這樣,如果父線程在兩個(gè)子線程調(diào)用打印語(yǔ)句
    之前調(diào)用exit,那么將不會(huì)有任何的打印輸出。這是因?yàn)閑xit函數(shù)將會(huì)退出進(jìn)程,同時(shí)釋放任務(wù),所以結(jié)束了所有的線程。
    任何線程(不論是父線程或者子線程)調(diào)用exit 都會(huì)終止所有其他線程。如果希望線程分別終止,可以使用pthread_exit函數(shù)。
    我們可以使用一個(gè)辦法彌補(bǔ)此缺陷。我們可以在父線程中插入一個(gè)延遲程序,給子線程足夠的時(shí)間完成打印的調(diào)用。同樣,
    在調(diào)用第二個(gè)之前也插入一個(gè)延遲程序保證第一個(gè)線程在第二個(gè)線程執(zhí)行之前完成任務(wù)。
    void print_message_function( void *ptr );
    main ( )
    {
    pthread_t thread1, thread2;
    char *message1 = "Hello”;
    char *message2 = "Wo r l d " ;
    pthread_create( &thread1, pthread_attr_default,
    (void *) &print_message_function, (void *) message1);
    sleep (10) ;
    pthread_create(&thread2, pthread_attr_default,
    (void *) &print_message_function, (void *) message2);
    sleep ( 10 ) ;
    exit (0) ;
    }
    void print_message_function( void *ptr )
    {
    char *message;
    message = (char *) ptr;
    printf("%s", message);
    pthread_exit(0) ;
    }
    這樣是否達(dá)到了我們的要求了呢?不盡如此,因?yàn)橐揽繒r(shí)間的延遲執(zhí)行同步是不可靠的。這里遇到的情形和一個(gè)分布程序和
    共享資源的情形一樣。共享的資源是標(biāo)準(zhǔn)的輸出設(shè)備,分布計(jì)算的程序是三個(gè)線程。
    其實(shí)這里還有另外一個(gè)錯(cuò)誤。函數(shù)sleep和函數(shù)e x i t一樣和進(jìn)程有關(guān)。當(dāng)線程調(diào)用sleep時(shí),
    整個(gè)的進(jìn)程都處于睡眠狀態(tài),也就是說(shuō),所有的三個(gè)線程都進(jìn)入睡眠狀態(tài)。這樣我們實(shí)際上沒(méi)有解決任何的問(wèn)題。
    希望使一個(gè)線程睡眠的函數(shù)是pthread_delay_np。例如讓一個(gè)線程睡眠2秒鐘,用如下程序:
    struct timespec delay;
    delay.tv_sec = 2;
    delay.tv_nsec = 0;
    pthread_delay_np( &delay );
    }
3. 線程同步
    POSIX提供兩種線程同步的方法,mutex和條件變量。mutex是一種簡(jiǎn)單的加鎖的方法來(lái)控制對(duì)共享資源的存取。
    我們可以創(chuàng)建一個(gè)讀/寫(xiě)程序,它們共用一個(gè)共享緩沖區(qū),使用mutex來(lái)控制對(duì)緩沖區(qū)的存取。
    void reader_function(void);
    void writer_function(void);
    char buf f e r ;
    int buffer_has_item = 0;
    pthread_mutex_t mutex;
    struct timespec delay;
    main( )
    {
    pthread_t reader;
    delay.tv_sec = 2;
    delay.tv_nsec = 0;
    pthread_mutex_init(&mutex, pthread_mutexattr_default);
    pthread_create( &reader, pthread_attr_default, (void*)&reader_function,
    N U L L ) ;
    writer_function( )
    void writer_function(void)
    {
    while( 1 )
    {
    pthread_mutex_lock( &mutex );
    if ( buffer_has_item == 0 )
    {
    buffer = make_new_item();
    buffer_has_item = 1;
    }
    pthread_mutex_unlock( &mutex );
    pthread_delay_np( &delay );
    }
    }
    void reader_function(void)
    {
    while( 1 )
    {
    pthread_mutex_lock( &mutex );
    if ( buffer_has_item == 1)
    {
    consume_item( buffer );
    buffer_has_item = 0;
    }
    pthread_mutex_unlock( &mutex );
    pthread_delay_np( &delay );
    }
    }
    在上面的程序中,我們假定緩沖區(qū)只能保存一條信息,這樣緩沖區(qū)只有兩個(gè)狀態(tài),有一條信息或者沒(méi)有信息。
    使用延遲是為了避免一個(gè)線程永遠(yuǎn)占有mutex。
    但mutex的缺點(diǎn)在于它只有兩個(gè)狀態(tài),鎖定和非鎖定。POSIX的條件變量通過(guò)允許線程阻塞和等待另一個(gè)線程的信號(hào)方法,
    從而彌補(bǔ)了mutex的不足。當(dāng)接受到一個(gè)信號(hào)時(shí),阻塞線程將會(huì)被喚起,并試圖獲得相關(guān)的mutex的鎖。
4. 信號(hào)量
   信號(hào)量是一個(gè)可以用來(lái)控制多個(gè)進(jìn)程存取共享資源的計(jì)數(shù)器。它經(jīng)常作為一種鎖定機(jī)制來(lái)防止當(dāng)一個(gè)進(jìn)程正在存取共享資源時(shí),
   另一個(gè)進(jìn)程也存取同一資源。這里我會(huì)講的很詳細(xì),我可是花了很多時(shí)間去找這資料呀!!
   下面先介紹一下信號(hào)量中涉及到的數(shù)據(jù)結(jié)構(gòu)。
   1.內(nèi)核中的數(shù)據(jù)結(jié)構(gòu)semid_ds
    和消息隊(duì)列一樣,系統(tǒng)內(nèi)核為內(nèi)核地址空間中的每一個(gè)信號(hào)量集都保存了一個(gè)內(nèi)部的數(shù)據(jù)結(jié)構(gòu)。數(shù)據(jù)結(jié)構(gòu)的原型是semid_ds。
    它是在linux/sem.h中做如下定義的:
   
    /*One semid data structure for each set of semaphores in the system.*/
    structsemid_ds{
    structipc_permsem_perm;/*permissions..seeipc.h*/
    time_tsem_otime;/*last semop time*/
    time_tsem_ctime;/*last change time*/
    structsem*sem_base;/*ptr to first semaphore in array*/
    structwait_queue*eventn;
    structwait_queue*eventz;
    structsem_undo*undo;/*undo requestson this array*/
    ushortsem_nsems;/*no. of semaphores in array*/
    };
   
    sem_perm是在linux/ipc.h定義的數(shù)據(jù)結(jié)構(gòu)ipc_perm的一個(gè)實(shí)例。它保存有信號(hào)量集的存取權(quán)限的信息,
    以及信號(hào)量集創(chuàng)建者的有關(guān)信息。
    sem_otime最后一次semop()操作的時(shí)間。
    sem_ctime最后一次改動(dòng)此數(shù)據(jù)結(jié)構(gòu)的時(shí)間。
    sem_base指向數(shù)組中第一個(gè)信號(hào)量的指針。
    sem_undo數(shù)組中沒(méi)有完成的請(qǐng)求的個(gè)數(shù)。
    sem_nsems信號(hào)量集(數(shù)組)中的信號(hào)量的個(gè)數(shù)。
   
    2.內(nèi)核中的數(shù)據(jù)結(jié)構(gòu)sem
    在數(shù)據(jù)結(jié)構(gòu)semid_ds中包含一個(gè)指向信號(hào)量數(shù)組的指針。此數(shù)組中的每一個(gè)元素都是一個(gè)
    數(shù)據(jù)結(jié)構(gòu)sem。它也是在linux/sem.h中定義的:
    /*One semaphore structure for each semaphore in the system.*/
    structsem{
    shortsempid;/*pid of las toperation*/
    ushortsemval;/*current value*/
    ushortsemncnt;/*num procs awaiting increase in semval*/
    ushortsemzcnt;/*num procs awaiting semval=0*/
    };
    sem_pid最后一個(gè)操作的PID(進(jìn)程ID)。
    sem_semval信號(hào)量的當(dāng)前值。
    sem_semncnt等待資源的進(jìn)程數(shù)目。
    sem_semzcnt等待資源完全空閑的進(jìn)程數(shù)目。
    以上說(shuō)的就是我們?cè)诔绦蚪?jīng)常用到的 (P/V)操作了
    P 操作( 代表荷蘭語(yǔ) proberen 意思是嘗試) :
        等待(wait)一個(gè)信號(hào)燈,該操作測(cè)試這個(gè)信號(hào)燈的值, 如果小于0||等于0, 那就等待(阻塞),
        一但值變大就將它減些 1.
        
    V 操作(代表荷蘭語(yǔ) verhogen 意思是增加):   
        掛出(post)一個(gè)信號(hào)燈, 該操作將信號(hào)燈的值加 1 .
        
   關(guān)于P/V 操作先介紹到這了,下面在介紹信號(hào)量的一些方法:
   semget()
   
    我們可以使用系統(tǒng)調(diào)用semget()創(chuàng)建一個(gè)新的信號(hào)量集,或者存取一個(gè)已經(jīng)存在的信號(hào)量集:
    系統(tǒng)調(diào)用:semget();
    原型:intsemget(key_t key,int nsems,int semflg);
    返回值:如果成功,則返回信號(hào)量集的IPC標(biāo)識(shí)符。如果失敗,則返回-1:errno=EACCESS(沒(méi)有權(quán)限)
    EEXIST(信號(hào)量集已經(jīng)存在,無(wú)法創(chuàng)建)
    EIDRM(信號(hào)量集已經(jīng)刪除)
    ENOENT(信號(hào)量集不存在,同時(shí)沒(méi)有使用IPC_CREAT)
    ENOMEM(沒(méi)有足夠的內(nèi)存創(chuàng)建新的信號(hào)量集)
    ENOSPC(超出限制)
    系統(tǒng)調(diào)用semget()的第一個(gè)參數(shù)是關(guān)鍵字值(一般是由系統(tǒng)調(diào)用ftok()返回的)。
    系統(tǒng)內(nèi)核將此值和系統(tǒng)中存在的其他的信號(hào)量集的關(guān)鍵字值進(jìn)行比較。打開(kāi)和存取操作與參數(shù)semflg中的內(nèi)容相關(guān)。
    IPC_CREAT如果信號(hào)量集在系統(tǒng)內(nèi)核中不存在,則創(chuàng)建信號(hào)量集。IPC_EXCL當(dāng)和IPC_CREAT一同使用時(shí),
    如果信號(hào)量集已經(jīng)存在,則調(diào)用失敗。如果單獨(dú)使用IPC_CREAT,則semget()要么返回新創(chuàng)建的信號(hào)量集的標(biāo)識(shí)符,
    要么返回系統(tǒng)中已經(jīng)存在的同樣的關(guān)鍵字值的信號(hào)量的標(biāo)識(shí)符。如果IPC_EXCL和IPC_CREAT一同使用,
    則要么返回新創(chuàng)建的信號(hào)量集的標(biāo)識(shí)符,要么返回-1。IPC_EXCL單獨(dú)使用沒(méi)有意義。
    參數(shù)nsems指出了一個(gè)新的信號(hào)量集中應(yīng)該創(chuàng)建的信號(hào)量的個(gè)數(shù)。
    信號(hào)量集中最多的信號(hào)量的個(gè)數(shù)是在linux/sem.h中定義的:
   
    #defineSEMMSL32/*
   semop()
        系統(tǒng)調(diào)用:semop();
        調(diào)用原型:int semop(int semid,struct sembuf*sops,unsign ednsops);
        返回值:0,如果成功。-1,如果失。篹rrno=E2BIG(nsops大于最大的ops數(shù)目)
        EACCESS(權(quán)限不夠)
        EAGAIN(使用了IPC_NOWAIT,但操作不能繼續(xù)進(jìn)行)
        EFAULT(sops指向的地址無(wú)效)
        EIDRM(信號(hào)量集已經(jīng)刪除)
        EINTR(當(dāng)睡眠時(shí)接收到其他信號(hào))
        EINVAL(信號(hào)量集不存在,或者semid無(wú)效)
        ENOMEM(使用了SEM_UNDO,但無(wú)足夠的內(nèi)存創(chuàng)建所需的數(shù)據(jù)結(jié)構(gòu))
        ERANGE(信號(hào)量值超出范圍)
            第一個(gè)參數(shù)是關(guān)鍵字值。第二個(gè)參數(shù)是指向?qū)⒁僮鞯臄?shù)組的指針。第三個(gè)參數(shù)是數(shù)組中的操作的個(gè)數(shù)。
            參數(shù)sops指向由sembuf組成的數(shù)組。此數(shù)組是在linux/sem.h中定義的:
        
        /*semop systemcall takes an array of these*/
        structsembuf{
        ushortsem_num;/*semaphore index in array*/
        shortsem_op;/*semaphore operation*/
        shortsem_flg;/*operation flags*/
        sem_num將要處理的信號(hào)量的個(gè)數(shù)。
        sem_op要執(zhí)行的操作。
        sem_flg操作標(biāo)志。
    如果sem_op是負(fù)數(shù),那么信號(hào)量將減去它的值。這和信號(hào)量控制的資源有關(guān)。如果沒(méi)有使用IPC_NOWAIT,
    那么調(diào)用進(jìn)程將進(jìn)入睡眠狀態(tài),直到信號(hào)量控制的資源可以使用為止。如果sem_op是正數(shù),則信號(hào)量加上它的值。
    這也就是進(jìn)程釋放信號(hào)量控制的資源。最后,如果sem_op是0,那么調(diào)用進(jìn)程將調(diào)用sleep(),直到信號(hào)量的值為0。
    這在一個(gè)進(jìn)程等待完全空閑的資源時(shí)使用。
    semctl()
        系統(tǒng)調(diào)用:semctl();
        原型:int semctl(int semid,int semnum,int cmd,union semunarg);
        返回值:如果成功,則為一個(gè)正數(shù)。
        如果失敗,則為-1:errno=EACCESS(權(quán)限不夠)
        EFAULT(arg指向的地址無(wú)效)
        EIDRM(信號(hào)量集已經(jīng)刪除)
        EINVAL(信號(hào)量集不存在,或者semid無(wú)效)
        EPERM(EUID沒(méi)有cmd的權(quán)利)
        ERANGE(信號(hào)量值超出范圍)
        
        系統(tǒng)調(diào)用semctl用來(lái)執(zhí)行在信號(hào)量集上的控制操作。這和在消息隊(duì)列中的系統(tǒng)調(diào)用msgctl是十分相似的。
        但這兩個(gè)系統(tǒng)調(diào)用的參數(shù)略有不同。因?yàn)樾盘?hào)量一般是作為一個(gè)信號(hào)量集使用的,而不是一個(gè)單獨(dú)的信號(hào)量。
        所以在信號(hào)量集的操作中,不但要知道IPC關(guān)鍵字值,也要知道信號(hào)量集中的具體的信號(hào)量。這兩個(gè)系統(tǒng)調(diào)用都使用了參數(shù)cmd,
        它用來(lái)指出要操作的具體命令。兩個(gè)系統(tǒng)調(diào)用中的最后一個(gè)參數(shù)也不一樣。在系統(tǒng)調(diào)用msgctl中,
        最后一個(gè)參數(shù)是指向內(nèi)核中使用的數(shù)據(jù)結(jié)構(gòu)的指針。我們使用此數(shù)據(jù)結(jié)構(gòu)來(lái)取得有關(guān)消息隊(duì)列的一些信息,
        以及設(shè)置或者改變隊(duì)列的存取權(quán)限和使用者。但在信號(hào)量中支持額外的可選的命令,這樣就要求有一個(gè)更為復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。
        系統(tǒng)調(diào)用semctl()的第一個(gè)參數(shù)是關(guān)鍵字值。第二個(gè)參數(shù)是信號(hào)量數(shù)目。
    參數(shù)cmd中可以使用的命令如下:
    ·IPC_STAT讀取一個(gè)信號(hào)量集的數(shù)據(jù)結(jié)構(gòu)semid_ds,并將其存儲(chǔ)在semun中的buf參數(shù)中。
    ·IPC_SET設(shè)置信號(hào)量集的數(shù)據(jù)結(jié)構(gòu)semid_ds中的元素ipc_perm,其值取自semun中的buf參數(shù)。
    ·IPC_RMID將信號(hào)量集從內(nèi)存中刪除。
    ·GETALL用于讀取信號(hào)量集中的所有信號(hào)量的值。
    ·GETNCNT返回正在等待資源的進(jìn)程數(shù)目。
    ·GETPID返回最后一個(gè)執(zhí)行semop操作的進(jìn)程的PID。
    ·GETVAL返回信號(hào)量集中的一個(gè)單個(gè)的信號(hào)量的值。
    ·GETZCNT返回這在等待完全空閑的資源的進(jìn)程數(shù)目。
    ·SETALL設(shè)置信號(hào)量集中的所有的信號(hào)量的值。
    ·SETVAL設(shè)置信號(hào)量集中的一個(gè)單獨(dú)的信號(hào)量的值。
    參數(shù)arg代表一個(gè)semun的實(shí)例。semun是在linux/sem.h中定義的:
    /*arg for semctl systemcalls.*/
    unionsemun{
    intval;/*value for SETVAL*/
    structsemid_ds*buf;/*buffer for IPC_STAT&IPC_SET*/
    ushort*array;/*array for GETALL&SETALL*/
    structseminfo*__buf;/*buffer for IPC_INFO*/
    void*__pad;
   
    val當(dāng)執(zhí)行SETVAL命令時(shí)使用。buf在IPC_STAT/IPC_SET命令中使用。代表了內(nèi)核中使用的信號(hào)量的數(shù)據(jù)結(jié)構(gòu)。
    array在使用GETALL/SETALL命令時(shí)使用的指針。
    下面的程序返回信號(hào)量的值。當(dāng)使用GETVAL命令時(shí),調(diào)用中的最后一個(gè)參數(shù)被忽略:
   
    intget_sem_val(intsid,intsemnum)
    {
    return(semctl(sid,semnum,GETVAL,0));
    }
   
        下面是一個(gè)實(shí)際應(yīng)用的例子:
   
    #defineMAX_PRINTERS5
    printer_usage()
    {
    int x;
    for(x=0;x
    注意系統(tǒng)調(diào)用semctl中的最后一個(gè)參數(shù)是一個(gè)聯(lián)合類型的副本,而不是一個(gè)指向聯(lián)合類型的指針。
    本文就先介紹到這了, 因?yàn)檫@方面的應(yīng)用太廣了! 怕說(shuō)多了就會(huì)錯(cuò)!~~
   
參考文獻(xiàn):
    UNIX 網(wǎng)絡(luò)編程 第2版 進(jìn)程間通迅  W.Richard Srevens 著
   



本文來(lái)自ChinaUnix博客,如果查看原文請(qǐng)點(diǎn):http://blog.chinaunix.net/u/8649/showart_89932.html
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國(guó)互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過(guò)ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP