2016-03-26 9 views
0

まず、rand()関数について多くの質問がありますが、これは異なると思います。C、rand関数がsleep()関数で正常に動作しない

実際には、sleep()関数と組み合わせていないときは、rand()関数が正常に動作します。私はそれを試してみました。しかし、この "sleep(rand()%5)"のようにrand()関数をsleep()関数と組み合わせると、すべての子プロセスにランダムな時間がかかることがありますが、最初の4-5人の子供、その後、残りのすべての子プロセスに対して0が生成されます。したがって、他の子プロセスは眠らない。そして時には、常にすべての子プロセスのための0を生成します。

私はUbuntu 64bitでコーディングしています。

私のコードについて: 私は親プロセスから8人の子供をフォークし、自分のPID番号を1つずつ出力したいと考えています。しかし、私は子供を作成した後にスリープ機能を使用する必要があります。睡眠時間はランダムでなければなりません。私はtime()関数をシードとして使用し、rand関数を使用しようとしましたが、スリープ関数では正しく機能しません。

は、ここに私のコードです:

#include <stdio.h> 
#include <sys/sem.h> 
#include <unistd.h> 
#include <wait.h> 
#include <stdlib.h> 
#include <time.h> 


void childs(); 
void parent(); 


int id; 
int i; 
int pidID[9]; 
int fd[2]; 
char buff[100]; 
int main(int argc, char *argv[]){ 
    pid_t child; 
    for(i = 0; i < 8; i++){ 
     pipe(fd); 

     child = fork(); 
     wait(NULL); 
     if(child){ 
      parent(); 
      continue; 
     }else if(child == 0){ 
      childs(); 
      break; 
     }else{ 
      perror("State\n"); 
      exit(1); 
     } 
    } 
    if(child ==0){ 
    printf("I am a child pid: %d, ppid: %d pidno: %d\n", getpid(), getppid(),pidID[i+1]); 
    }else{ 
    printf("I am a parent pid: %d, ppid: %d pidno: %d\n", getpid(), getppid(),pidID[0]); 
    } 

} 


void childs(){ 
id = getpid(); 
pidID[i + 1] = id; 
char swap[50]; 
sprintf(swap, "%d" ,id); 
write(fd[1], swap, 10); 
srand(time(NULL)); 
int randomTime = rand() %5; 
printf("Random time: %d\n",randomTime); 
sleep(randomTime); 
} 



void parent(){ 
pidID[0] = getpid(); 
read(fd[0], buff , 10); 
printf("Buff: %s\n", buff); 
} 
+0

"うまくいく"という意味を定義し、 "0"となることを意味します... "。 – Olaf

+0

私は時々rand()の製品乱数を意味します。しかし時には製品は0だけです。今質問を編集します。 – Ayse

+0

コードを適切に書式設定してインデントします。非プロトタイプの関数宣言子は、標準によって推奨されなくなりました。それらを使用しないでください。 – Olaf

答えて

2

とき、それぞれの子プロセスでtime(NULL)srand、同じ値でシードされます同じ秒に発売すべての子供たち。もちろん

第二の子sleep場合は常に眠っていたならば、物事はほとんど出て動作しますので、関与sleepwaitで、彼らは、新しい値でシードます。

しかし、rand() % 5は0と4の間の値を生成します。与えられたtimeシードが最初のrand()の出力を5の倍数にし、0秒間スリープした場合、その子は直ちに終了し、ループは最大で数ミリ秒の間隔で新しい子をフォークします。 time reseedがrandの最初の出力を5の倍数ではない値に変更するまで、これは2番目(またはそれ以上)の間、これを続けます。

int randomTime = rand() %5 + 1; // Range 1-5, or use rand() % 4 + 1 for 1-4 

ので、あなたがより少ないの睡眠を持っていることはありません:

int randomTime = rand() %5; 

に:あなたはこれを修正したい場合は

、(まだ愚かな場合は)最も簡単な方法は、変更することです第二に、同じゼロ秒睡眠を何度も繰り返す同じ時間で常に再摂取するという病理学的事例には決して入らない。

また、ゼロ秒のスリープが可能でなければならない場合は、さらに細かいtime関数を使用して、より急速に変化するシードを取得してください。いくつかの値を変更したために

struct timespec tm; 
clock_gettime(CLOCK_MONOTONIC, &tm); 
// xor-ing with tv_nsec >> 31 to ensure even low precision clocks vary 
// the low 32 bits 
srand((unsigned)(tm.tv_sec^tm.tv_nsec^(tm.tv_nsec >> 31))); 

を、あなたはsrand sの間の時間が十分に長くなければならないので、rand() % 5を継続して使用することができます。たとえば、POSIXシステムでは、代わりにはるかに急速に変わるべきclock_gettimeを使用する場合がありますtv_nsecにあり、別のシード値を取得します。

+0

意味があります。どうもありがとう! – Ayse

+0

ここには、各子供を別々に播種するための提案があります.pidにミックスしてください:http://stackoverflow.com/a/8623196/12711 –

+0

@MichaelBurr:良い点。技術的には、次の起動前に各子供が退出するので、奇妙なシステムが同じPIDを繰り返し再発行するだけではないという保証はありません(実際には私が見たすべてのシステムは、使用されていないPIDはすべて一度発行されていますが、それは必須ではないと思うので、病理学的なシステムがあなたを混乱させる可能性があります)。あなたが同時に多くの子供が走っていたなら、それはどんなところでもうまくいくでしょう。 – ShadowRanger

関連する問題