2016-03-26 23 views
0

Her şeyden önce rand() işleviyle ilgili birçok soru olduğunu biliyorum, ancak bunun farklı olduğunu düşünüyorum.C, rand işlevi sleep() işleviyle düzgün çalışmıyor

Aslında, sleep() işleviyle birleştirmediğimde rand() işlevi her zaman düzgün çalışır. Denedim. Fakat rand() işlevini, bu "uyku (rand()% 5)" gibi uyku() ile birleştirdiğimde, beklediğim gibi bazen tüm çocuk süreçleri için ürün rastgele bir süre, ancak bazen ilk 4-5 çocuk için iyi çalışır, bundan sonra kalan tüm çocuk süreçleri için 0 ürün. Yani diğer çocuk süreçleri uyumuyor. Ve bazen her çocuk süreçleri için 0 ürün.

BTW, Ubuntu 64bit kodluyorum.

Kodum hakkında: Ebeveyn işleminden 8 çocuğu işemek ve pid numaralarını tek tek basmak istiyorum. Ama bir çocuk oluşturduktan sonra uyku fonksiyonunu kullanmalıyım. Uyku zamanı rastgele olmalıdır. Bir tohum olarak time() işlevini kullandım ve rand işlevini kullanmaya çalıştım ancak uyku işleviyle düzgün çalışmıyor.

İşte benim kodudur:

#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

"İyi çalışıyor" ile ne demek istediğinizi ve "0" olur ... ile ne demek istediğinizi tanımlayın. – Olaf

+0

Bazen beklediğim gibi rand() ürünleri rastgele sayılar demek istiyorum. Ama bazen sadece 0 ürün. Şimdi soruyu düzenleyeceğim. – Ayse

+0

Kodunuzu biçimlendirin ve doğru şekilde girin. Ve prototip olmayan fonksiyon belirleyicileri standart tarafından onaylanmamıştır. Onları kullanma. – Olaf

cevap

2

zaman her çocuk süreçte time(NULL) ile srand, aynı değere sahip tohum olacak Aynı saniyede başlatılan tüm çocuklar. sleep ve ilgili wait ile Tabii

, işler çoğunlukla her zaman uyurken olmadığını çalışacak, böylece bir saniye çocuk sleep, bunlar yeni bir değerle tohum edersen.

Ancak rand() % 5 0 ve 4 arasında değerler üretir; İlk verilen bir time ilk kez ilk rand() çıktısının beş katın katına çıkmasına neden olur, siz 0 saniyede uyursunuz, çocuk hemen hemen çıkar ve döngü yeni bir çocuk ister, hepsi birkaç milisaniye kaçsa . Ve bu,yeniden gönderimi, rand'un ilk çıktısını beşin katları olmayan bir değere dönüştürene kadar (veya daha fazla) katı bir saniye için yapmaya devam edecektir.

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

böylece bir daha az bir uyku asla:

int randomTime = rand() %5; 

için: Bu düzeltmek istiyorsanız

, (hala saçma ise) en basit yaklaşım değiştirmektir İkincisi, ve aynı zamanla aynı sıfır saniye uykuyu üreten aynı zamanla tekrar tekrar patolojik vakaya giremezsiniz.

Alternatif olarak, sıfır saniye uykular bir olasılık olmalı, daha hızlı değişen bir tohum almak için daha ince taneli bir time işlevini kullanın. Birkaç değerleri değişmiş

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))); 

ve srand s arasındaki zaman yeterli uzunlukta olmalıdır çünkü rand() % 5 kullanmaya devam edebilirsiniz: Örneğin, bir POSIX sisteminde, bunun yerine çok daha hızlı bir şekilde değişir hangi clock_gettime kullanabilir tv_nsec'da farklı bir tohum değeri elde edin.

+0

Mantıklı. Çok teşekkürler! – Ayse

+0

Her çocuğun farklı şekilde tohumlanması için bir öneri - pid karıştırın: http://stackoverflow.com/a/8623196/12711 –

+0

@MichaelBurr: İyi nokta. Her ne kadar teknik olarak, her çocuk bir sonraki lansmanlardan önce çıktığı için, garip bir sistemin tekrar tekrar aynı PID'yi yeniden yayınlayamayacağına dair bir garanti yoktur (pratikte, döngüleri gördüğüm her sistem, böylece yeniden yayınlanmayacaktır) kullanılmayan tüm PID'ler bir kez yayınlandı, ancak bu zorunlu olduğunu sanmıyorum, bu kadar patolojik sistemler sizi rahatsız edebilir). Aynı anda çalışan birçok çocuğunuz olsaydı, ne olursa olsun iyi çalışırdı. – ShadowRanger