get a values from child to use it in parent - c

i wrote the code below but the last printf return 0 for sumofall how can i get the values of sumoro,sumort and sumorth from child
the code :
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
int main()
{
int array[3][3];
int sumoro = 0,sumort = 0,sumorth = 0;
pid_t pid = fork();
if (pid < 0) {
printf("fork faild");
exit(1);
}
else {
if (pid == 0)
{
for (int i = 0; i < 3 ; i++) {
for (int j = 0; j < 3; j++) {
array[i][j] = rand()%9;
if (i == 0)
sumoro += array[0][j];
if (i == 1)
sumort += array[1][j];
if (i == 2)
sumorth += array[2][j];
}
}
}
else {
waitpid(pid, NULL, 0);
int sumofall = sumoro + sumort + sumorth;
printf("sum of all equal : %d ", sumofall);
}
return 0;
}
}
Note : not necessarily but if you can help me, how can i make the rand() gives everytime new numbers because i notice every time same values

When you fork, each process resides in its own space afterwards. There is no easy way to move data back and forth - at least nothing as simple as reading a variable. You need to use some kind of Inter-Process Communication (IPC) method, such as anonymous pipes (see the pipe(2) manual page).
As for rand(), you need to seed the random number generator with a relatively random value. A simple solution with adequate randomness for pretty much anything but cryptography is issuing this statement once at the beginning of your program:
srand(time(NULL));
This uses the clock to seed the RNG with different values each time that you run your program, unless you manage to run it twice withing the same second.

Basically the part where you add up your values and where you print them are on different processes.
For rand() what you need to do is initialize it with a seed, by default it is seeded with 0, that's why it's always giving you the same sequence (how are you seeing the values rand gives you anyway?). What is usually done is to seed it with the time/date so that it's always different, try using
srand ( time(NULL) );
for that make sure to #include <time.h>

Related

Random-filled vector always returns the same numbers

I am completely new in C and try to fill a vector with random integers and output it afterwards. However, it seems that the vector is always filled with the same number. What do I need to change to really get random payments? There is no limit, the number should only be within the value range of long. Here's my code:
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <time.h>
int main()
{
long x = 20;
long y = 12;
std::vector<long> entries;
//initialize simple random number generator using current time
srand(time(NULL));
for (int step = 0; step < x; step++) {
entries.push_back(rand());
++entries[step];
}
for (std::vector<long>::const_iterator i = entries.begin(); i != entries.end(); ++i) {
printf("%ld\n", i);
}
return 0;
}
EDIT:
I want to solve the issue using plain C not c++!
The main problem in your code is in your last loop
for (std::vector<long>::const_iterator i = entries.begin(); i != entries.end(); ++i) {
printf("%ld\n", i);
}
You're not printing a value from the vector, but an iterator that's pointing to it
Change the line inside the loop to printf("%ld\n", *i); to fix it.
Better yet, you can use a range-loop to make it even simplier
for(auto& number : entries){
std::cout<<number<<'\n'; //or printf("%ld\n",number), like in your code
}
If you want your solution to be pure C, you'll need to use arrays instead of vectors.
I'm missing some informations here, but a basic C program that uses srand() and rand() would look like this :
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#define NB_ENTRIES (20)
#define RANDOM_MAX_RANGE (50) // you should update that
// Don't use srand(time(NULL)) because if you start many time this
// program too quickly, you'll have the same values in all instances.
void Randomize(void)
{
struct timeval time;
gettimeofday(&time,NULL);
srand((time.tv_sec * 1000) + (time.tv_usec / 1000));
}
// Returns a value between 0 and toNumber-1
// Thanks to Bathsheba for pointing out an error with my first version.
int RandomInt(int toNumber)
{
return (int)(rand()/(RAND_MAX + 1.0) * toNumber);
}
// This better but slower version of RandomInt() will ensure
// an even distribution of random values if toNumber is
// greater than around three quarter of RAND_MAX
// NOTE : toNumber must be between 0 and RAND_MAX.
int BetterRandomInt(int toNumber)
{
const int randomSize = RAND_MAX / toNumber;
int returnValue;
do
{
returnValue = rand() / randomSize;
}
while (returnValue >= toNumber);
return returnValue;
}
int main(void)
{
int entries[NB_ENTRIES];
int step;
Randomize();
for (step = 0; step < NB_ENTRIES; step++)
{
entries[step] = RandomInt(RANDOM_MAX_RANGE);
// entries[step] = BetterRandomInt(RANDOM_MAX_RANGE);
}
for (step = 0; step < NB_ENTRIES; step++)
{
printf("%d\n", entries[step]);
}
return 0;
}
Note that I'm using a fixed number of entries. You can make your array dynamic by using pointers and malloc(). Just comment if you need that, but I felt it was out of scope of the question.

C How to Keep a Random Variable From Repeating the Same Number

So I'm just learning C and I would like to know how you could prevent a variable randomized with the rand() function from repeating the same number. I have a script which simply randomizes and prints a variable in a for loop 4 times. How could I make it so the variable never gets the same number after each time it uses the rand() function?
#include <stdio.h>
#include <stdlib.h>
int randomInt;
int main()
{
srand(time(0));
for (int i = 0; i < 4; ++i) {
randomInt = rand() % 4;
printf("%d\n", randomInt);
}
return 0;
}
On most machines, int is 32 bits. So after 232 iterations, you are sure that you'll get some repetition (and probably much before).
If you restrict yourself to much less loops, consider e.g. keeping an array of previously met random numbers (or some hash table, or some binary tree, or some other container).
For a loop repeated only 4 times, keeping an array of (at most 4-1) previously emitted numbers is quite simple, and efficient enough.
Read also about the pigeonhole principle.
A slightly different approach.
int set[] = {0, 1, 2, 3 } ;
srand(time(0));
shuffle(set,4);
using the shuffle algorithm given in this question
https://stackoverflow.com/a/6127606/9288531
I'm guessing that you are getting the same numbers because your are running your program multiple times within the same second. If time(0) hasn't changed, you will have the same seed and the same random numbers generated. Unless your program runs extremely quickly, I imagine using a seed based on microseconds instead of seconds would work:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
int randomInt;
int main()
{
struct timeval my_microtimer;
gettimeofday(&t1, NULL);
srand(t1.tv_sec * my_microtimer.tv_usec);
for (int i = 0; i < 4; ++i) {
randomInt = rand() % 4;
printf("%d\n", randomInt);
}
return 0;
}
What you could do is keeping track of each number you already generated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int hasMyNumberAlreadyBeenGenerated(int number, int generatedNumbers[], int size){
for(int i = 0; i < size + 1; i++){
//If you already generated the number, it should be present somewhere in your array
if(generatedNumbers[i] == number) return 1;
//If you did not, find the first available space in your array, and put the number you generated into that space
if(generatedNumbers[i] == 0){
generatedNumbers[i] = number;
break; //No need to continue to check the array
}
}
return 0;
}
int main()
{
int randomInt;
int generatedNumbers[4];
//We set "0" in all the array, to be sure that the array doesn't contain unknown datas when we create it
memset(generatedNumbers, 0x0, sizeof(generatedNumbers));
srand(time(0));
for (int i = 0; i < 4; ++i) {
randomInt = rand() % 4 + 1;
//As long as the number you generate has already been generated, generate a new one
while(hasMyNumberAlreadyBeenGenerated(randomInt, generatedNumbers, i) == 1){
randomInt = rand() % 4 + 1;
}
printf("generated : %d\n", randomInt);
}
return 0;
}
The problem with this method is that you can't generate a 0, because if you do you'll endlessly loop.
You can bypass this problem using a dynamic array using malloc() function.
If you want to write clean code you should define how many numbers you want to generate with a #define.
What you seem to be asking is a non-random set of numbers 0 to 3 in a random order. Given that;
int set[] = {0, 1, 2, 3 } ;
int remaining = sizeof(set) / sizeof(*set) ;
while( remaining != 0 )
{
int index = rand() % sizeof(set) / sizeof(*set) ;
if( set[index] > 0 )
{
printf( "%d\n", set[index] ) ;
set[index] = -1 ;
remaining-- ;
}
}
For very large sets, this approach may not be practical - the number of iterations necessary to exhaust the set is non-deterministic.

Forked 10 child processes, how can the parent process collect their return values?

I have to find the biggest value in an array of a 1000 numbers with 10 child processes (so that every one of them only checks a hundred values), and the parent only has to collect the data.
I'm already done with the whole thing, but I'm stuck at reading the values.
Here's the code:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main(){
int array[1000];
int i, j;
int pids[10];
int searchminindex;
int searchmaxindex;
int maxindex;
srand(time(NULL));
//fill up array with random numbers
for(i = 0; i < 1000; i++)
{
tomb[i] = random() % 5000;
}
//create 10 child processes
for (i = 0; i < 10; i++) {
if ((pids[i] = fork()) < 0) {
perror("fork");
abort();
}
else if (pids[i] == 0) {
searchminindex = i * 100;
searchmaxindex = (i+1) * 100;
//finding the biggest value
maxindex = searchminindex;
for(j = searchminindex+1; j < maxindex; j++) {
if( array[maxindex] < array[j])
maxindex = j;
}
}
}
for(i = 0; i < 10; i++){
//here's where I'd read the return values of the subarrays
}
return 0;
}
I've tried using pipes and also using WEXITSTATUS, but I'm really confused and don't know where to close one end of the pipe and things like that, and with WEXITSTATUS I'm completely lost.
Any way you could help?
You need to test the pid returned from fork, and branch your code so your main process doesn't act like a child, and so that your children don't spawn children of their own. Once that's taken care of...
An alternative to mmap or setting up shared memory at all is to use WEXITSTATUS. According to the man page, it'll only return the least significant 8 bits, so if your return values can be greater than 127, this is likely not your best option. Can be made to work up to 255, but be careful about signedness of char, it's not standard.
int returned_values[10];
for(int i = 0; i < 10; ++i)
{
int status;
wait(&status);
if(WIFEXITED(status))
returned_values[i] = WEXITSTATUS(status);
else {
//Do something more meaningful here
//This means a child received a signal, or any of the other ways wait returns other than a child exiting.
--i;
}
You need to test the pid returned from fork, and branch your code so your main process doesn't act like a child, and so that your children don't spawn children of their own. Once that's taken care of...
Sharing memory between forked processes is explained well here
I would use mmap to create shared memory between the processes, you'll need to specify for each process where to put it's result, then use wait to determine when all children have exited, and a good program would evaluate the exit status and inform the user if any child exited abnormally.
Don't forget to clean up the shared memory before the parent exits.

Squaring numbers w/ multiple threads

I'm trying to write a program that squares numbers 1-10,000 by creating 8 threads and each thread will take turns squaring ONE NUMBER EACH. Meaning that one thread will square 1, another will square 2, etc until all threads square a number. Then one thread will square 9, etc, all the way to 10,000. My code is below:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <pthread.h>
#include <sys/types.h>
#define NUMBER_OF_THREADS 8
#define START_NUMBER 1
#define END_NUMBER 10000
FILE *f;
void *sqrtfunc(void *tid) { //function for computing squares
int i;
for (i = START_NUMBER; i<= END_NUMBER; i++){
if ((i % NUMBER_OF_THREADS) == pthread_self()){ //if i%8 == thread id
fprintf(f, "%lu squared = %lu\n", i, i*i); //then that thread should do this
}
}
}
int main(){
//Do not modify starting here
struct timeval start_time, end_time;
gettimeofday(&start_time, 0);
long unsigned i;
f = fopen("./squared_numbers.txt", "w");
//Do not modify ending here
pthread_t mythreads[NUMBER_OF_THREADS]; //thread variable
long mystatus;
for (i = 0; i < NUMBER_OF_THREADS; i++){ //loop to create 8 threads
mystatus = pthread_create(&mythreads[i], NULL, sqrtfunc, (void *)i);
if (mystatus != 0){ //check if pthread_create worked
printf("pthread_create failed\n");
exit(-1);
}
}
for (i = 0; i < NUMBER_OF_THREADS; i++){
if(pthread_join(mythreads[i], NULL)){
printf("Thread failed\n");
}
}
exit(1);
//Do not modify starting here
fclose(f);
gettimeofday(&end_time, 0);
float elapsed = (end_time.tv_sec-start_time.tv_sec) * 1000.0f + \
(end_time.tv_usec-start_time.tv_usec) / 1000.0f;
printf("took %0.2f milliseconds\n", elapsed);
//Do not modify ending here
}
I am not sure where my error is. I create my 8 threads in main, and then depending on their thread id (tid), I want that thread to square a number. As of right now, nothing is being printed into the output file and I can't figure out why. Is my tid comparison not doing anything? Any tips are appreciated. Thanks guys.
First, you intentionally pass a parameter to each thread so it know which thread it is (from 0 to 7) That is good, but you then don't use it anymore inside the thread (this leads to one of the possible confussions you have)
Second, as you say in the explanation of how the algorithm should go, you say each thread must square a different set of numbers, but all of them do square the same set of numbers (indeed the whole set of numbers)
You have two approaches to this: Let each thread square the number, and go for the next, eight places further (so the algorithm is the one described in your explanation) or you give different sets (each 1250 consecutive numbers) and let each thread act on is own separate interval.
That said, you have to reconstruct your for loop to do one of two:
for (i = parameter; i < MAX; i += 8) ...
or
for (i = 1250*parameter; i < 1250*(parameter+1); i++) ...
that way, you'll get each thread run with a different set of input numbers.

Pipe for multiple processes

Currently working on some homework and having a hard time. The goal is to generate 100,000 numbers and add them all together by dividing the work into 10 processes (10,000 numbers each)
I think I've figured out how to fork processes (hopefully), but using Pipe() to relay the subtotals from each child process is not working... the program below returns 44901 for each child process and 449010 for the running total.
I'm struggling hard but I feel like this is something simple I should be able to understand.
main()
{
int i;
pid_t pid;
int status = 0;
int fd[2];
int runningTotal = 0;
pipe(fd);
int t;
int r;
for (i = 0; i < 10; i++) {
pid = fork();
if (pid == 0){
close(fd[0]);
t = ChildProcess();
write(fd[1], &t, sizeof(t));
exit(0);
}
close(fd[1]);
read(fd[0], &r, sizeof(r));
runningTotal = runningTotal + r;
wait(&status);
}
printf("%i\n", runningTotal);
}
int ChildProcess() {
int i;
int total = 0;
int r = 0;
for (i = 0; i < 10000; i++) {
r = rand() % 10; // 0 to 10
total = total + r;
}
printf("%i\n", total);
return total;
}
Ordinarily, one would use a separate pipe for each child, for otherwise it's impossible for the parent to know from which process the data it reads comes. I don't think that's so much of an issue in this particular case, though, because here, you actually don't care. Although it still makes me cringe a bit, I think you indeed can get away with just one pipe for this particular task.
In fact, I don't think your problem is with the pipe at all. It is with rand(). All child processes compute exactly the same sequence of (pseudo-)random numbers because they all use the same (default) seed. If you want to produce different sequences of numbers, then you need to call srand() in each child process, giving a different seed in each one. The sequence of numbers rand() will generate is completely determined by the seed with which it starts.
Note, too, that if the system's random number generator is any good at all, then all the sums computed by the various processes should be very close to each other, and to the result you reported. This is a consequence of the Central Limit Theorem in statistics, but you can think of it simply as the larger results balancing the smaller ones on average. There's probably a slight bias arising from calculating the remainder mod 10.
Initial diagnosis
If your concern is that the children are all producing the same values, then the problem is that they're all using the same random sequence because you don't call srand() anywhere. You need to call it once per child, with a different seed for each child.
It isn't 100% reliable, but you could probably get away with srand(time(0) + getpid()); in each child — or even just getpid() since those values are guaranteed to be different.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
int ChildProcess(void)
{
int total = 0;
srand(time(0) + getpid());
for (int i = 0; i < 10000; i++)
{
int r = rand() % 10; // 0 to 9 (not 10).
total = total + r;
}
printf("%i\n", total);
return total;
}
Further scrutiny
Actually, on closer examination, there's another problem. The parent process closes the write end of the pipe after forking the first child, so the subsequent children don't have a usable file descriptor to use. The read value will always be the one from the first child. So, you need to do more serious work.
int main(void)
{
int fd[2];
pipe(fd); // Missing error check
for (int i = 0; i < 10; i++) {
pid_t pid = fork();
if (pid == 0){
close(fd[0]);
int t = ChildProcess();
write(fd[1], &t, sizeof(t)); // Missing error check?
exit(0);
}
// Print PID here? Error check?
}
close(fd[1]);
int r;
int runningTotal = 0;
while (read(fd[0], &r, sizeof(r)) > 0) // Debugging opportunities here
runningTotal = runningTotal + r;
while (wait(0) > 0) // Lots of debugging opportunities here
;
printf("%i\n", runningTotal);
return 0;
}
given this code: (an excerpt from the posted code)
for (i = 0; i < 10; i++) {
pid = fork();
if (pid == 0){
close(fd[0]);
t = ChildProcess();
write(fd[1], &t, sizeof(t));
exit(0);
}
close(fd[1]);
read(fd[0], &r, sizeof(r));
runningTotal = runningTotal + r;
wait(&status);
}
there is a sequence problem.
When the parent closes the fd[1] during the first iteration of the loop, that file descriptor does not 'magically' open again for the next iteration of the loop.
The code for the parent, in the loop, needs to check the returned value from the call to read() to assure the operation was successful. (it probably was not successful after the first iteration through the loop, so the variable 'r' will be unchanged.

Resources