12_競態條件(時序競態)

/*
    sleep函數幾點說明
    1sleep函數作用,讓進程睡眠。
    2)能被信號打斷,然後處理信號函數以後,就不再睡眠了。直接向下執行代碼
    3sleep函數的返回值,是剩餘的秒數

*/
//sleep是可被中斷的睡眠,但不一定睡夠100s
//sleep是可中斷的睡眠
void handler(int num)
{
    printf("recv num:%d \n", num);  
    if (num == SIGQUIT)
    {
        //exit(0);
    }
}

#if 1
void test()
{
    int n = 100;
    pid_t   pid;
    printf("main ....begin\n");
    signal(SIGINT, handler);
    sleep(n);  //sleep是可中斷睡眠,讓進程睡夠 
    printf("sleep ....結束\n");
}
#endif
//利用sleep()函數的返回值使程序足夠的睡眠
#if 0
void test()
{
    int n = 100;
    printf("main ....begin\n");
    signal(SIGINT, handler);

    //進程醒過來再繼續睡,保證睡夠100s
    do 
    {
        n = sleep(n);  //sleep是可中斷睡眠,讓進程睡夠 
        if(n != 0){
            printf("還剩餘 %d 秒, 要給睡夠。。。。。\n", n);
        }else{
            printf("TMD,終於睡醒了。。。。。。\n");
        }
    } while(n > 0);
    printf("sleep ....結束\n");
}
#endif


int main(void)
{

    test();
    return 0;
}
/*
  使用自定義的sleep1()與真正的sleep()的實現。
  但會有3 個問題:
  1)在sleep1()之前調用alarm
  2)程序修改了SIGALRM信號的默認行爲
  3)alarm()與pause()之間有競爭條件,若alarm()在調用pause之前超時
  ,並調用了信號處理程序,此時調用pause後,因沒有捕捉到其他信號處理函數
  ,造成函數永久被掛起
  解決辦法參考apue 339頁
*/
#if 1

void  sig_alrm(int signo)
{
    //什麼也不做,僅僅是喚醒pause
        printf("收到SIGALRM 信號\n");
}

unsigned int sleep1(unsigned int seconds)
{
    if(signal(SIGALRM, sig_alrm) == SIG_ERR){
        return seconds; 
    }
    printf("set seconds = %d, but 返回值是 %d\n",seconds, alarm(seconds));//開始定時器
    pause();//主動掛起
    return (alarm(0));//關閉定時器,返回剩餘的時間
}

void test()
{
    int ret = 0;
    //alarm(3);
    ret = sleep1(7);
    printf("剩餘的秒數:%d\n", ret);
}
#endif

int main(void)
{
    test();
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章