2016-03-26 9 views
0

Zunächst einmal weiß ich, es gibt eine Menge Fragen über rand() Funktion, aber ich denke, das ist anders.C, rand funktioniert nicht richtig mit sleep() Funktion

Eigentlich funktioniert die Funktion rand() immer richtig, wenn ich nicht mit der Funktion sleep() kombiniert habe. Ich versuchte es. Aber wenn ich die Funktion rand() mit sleep() wie dieser "sleep (rand()% 5) kombiniere", ist es manchmal zufällige Zeit für alle Kindprozesse, wie ich es erwartet habe, aber manchmal funktioniert es gut für die ersten 4-5 Kinder. Danach wird 0 für alle verbleibenden untergeordneten Prozesse erstellt. So schlafen andere Kinderprozesse nicht. Und manchmal gibt es immer Produkte 0 für alle Kindprozesse.

BTW, ich codiere auf Ubuntu 64bit.

Über meinen Code: Ich möchte 8 Kinder vom Elternprozess abzweigen und ihre pid Zahlen eins nach dem anderen drucken. Aber ich sollte die Schlaffunktion nach dem Erstellen eines Kindes verwenden. Die Schlafzeit sollte zufällig sein. Ich habe die time() -Funktion als Seed verwendet und versuche die Rand-Funktion zu verwenden, aber sie funktioniert nicht richtig mit der Sleep-Funktion.

Hier ist mein Code:

#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

Definieren Sie, was Sie mit "funktioniert gut" und was Sie meinen mit "wird' 0 "... gemeint. – Olaf

+0

Ich meine manchmal rand() Produkte Zufallszahlen, wie ich erwartet habe. Aber manchmal sind es nur Produkte 0. Ich werde jetzt die Frage bearbeiten. – Ayse

+0

Formatieren Sie Ihren Code und ziehen Sie ihn richtig ein. Und Nicht-Prototyp-Funktionsdeklaratoren werden vom Standard nicht mehr unterstützt. Benutze sie nicht. – Olaf

Antwort

2

Wenn Sie srand mit time(NULL) in jedem Kindprozess, alle in der gleichen Sekunde gestartet Kinder wird mit dem gleichen Wert Saatgut.

Natürlich mit dem sleep und wait beteiligt, wenn die Kinder sleep für eine Sekunde, sie mit einem neuen Wert Samen werden, so die Dinge meist aus funktionieren würde, wenn man immer schliefen.

Aber rand() % 5 erzeugt Werte zwischen 0 und 4; das erste Mal, dass eine gegebene time Seed würde die erste rand() Ausgabe ein Vielfaches von fünf sein, schlafen Sie für 0 Sekunden, das Kind fast sofort beendet, und die Schleife gabelt ein neues Kind, alle in dem Raum von ein paar Millisekunden . Und es wird dies für eine feste Sekunde (oder mehr) tun, bis die time Reed-Operation die erste Ausgabe von rand auf einen Wert ändert, der kein Vielfaches von fünf ist.

Wenn Sie dieses Problem beheben möchten, ist die einfachste (wenn noch albern) Ansatz wäre zu ändern:

int randomTime = rand() %5; 

zu:

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

so haben Sie nie einen Schlaf von weniger als ein Zweitens, und du gehst nie in den pathologischen Fall ein, dass du ständig mit der gleichen Zeit neu säst, die immer wieder den gleichen Null-Sekunden-Schlaf erzeugt.

Alternativ, wenn Null-Sekunden-Schlaf eine Möglichkeit sein muss, verwenden Sie eine feinkörnigere time-Funktion, um einen schneller variierenden Samen zu erhalten. Zum Beispiel auf einem POSIX-System, können Sie stattdessen clock_gettime verwenden, die viel schneller verändern sollte:

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

und Sie können weiterhin rand() % 5 verwenden, da die Zeit zwischen srand s sollte lang genug sein, um ein paar Werte geändert haben in tv_nsec und erhalten einen anderen Startwert.

+0

Es macht Sinn. Danke vielmals! – Ayse

+0

Hier ist ein Vorschlag für die Seeding jedes Kind anders - mischen in der PID: http://StackOverflow.com/a/8623196/12711 –

+0

@MichaelBurr: Guter Punkt. Obwohl jedes Kind vor den nächsten Starts technisch beendet wird, gibt es keine Garantie dafür, dass ein seltsames System nicht immer wieder die gleiche PID wieder ausgibt (in der Praxis läuft jedes System, das ich je gesehen habe, zyklisch, so dass es erst wieder ausgegeben wird) alle unbenutzten PIDs wurden einmal ausgegeben, aber ich glaube nicht, dass das obligatorisch ist, also könnten pathologische Systeme Sie durcheinander bringen). Wenn du viele Kinder gleichzeitig laufen hättest, würde das ohne Probleme funktionieren. – ShadowRanger

Verwandte Themen