Hi everyone!
So my task is this: Make a program in C which runs three processes (A,B,C), which use a common memory (buffer). Process A generates 50 random numbers and writes then into the buffer. Process B writes down every even number into file F1. Process C writes down every odd number into file F2.
So far I have this code:

#include<fcntl.h>
#include<wait.h>
#include<stdio.h>
#include<unistd.h>
#include<time.h>
using namespace std;
 
extern char* getmem(int);
 
int main(){
	int ID=0, nID, status=0;
	int i;
	short *a=(short*)getmem(3271);
	FILE *f;
	srand((unsigned)time(NULL));
	// Defining the processes
	cout<<"Starting process A...\n";
	ID++;
	nID=fork();
	if(nID<0){
		cout<<"Error!\n";
		return 0;
	}
	else if(nID!=0){
		wait(&status);
		cout<<"Starting process B...\n";
		ID++;
		nID=fork();
		if(nID<0){
			cout<<"Error!\n";
			return 0;
		}
		else if(nID!=0){
			cout<<"Starting process C...\n";
			ID++;
			nID=fork();
			if(nID<0){
				cout<<"Error!\n";
				return 0;
			}
			else if(nID!=0)
				ID=0;
		}
	}
	// The processes
	if(ID==1)
		for(i=0; i<50; i++){
			*(a+i)=rand();
		}
	if(ID==2){
		f=fopen("f1.txt", "w");
		if(f==NULL)
			cout<<"Error creating file!\n";
		for(i=0; i<50; i++){
			if((*(a+i)%2)==0)
				fprintf(f, "%i\n", *(a+i));
		}
		fclose(f);
	}
	if(ID==3){
		f=fopen("f2.txt", "w");
		if(f==NULL)
			cout<<"Error creating file!\n";
		for(i=0; i<50; i++){
			if((*(a+i)%2)!=0)
				fprintf(f, "%i\n", *(a+i));
		}
		fclose(f);
	}
	wait(&status);
	return 0;
}

But it gets me errors about declaration of srand(), cout, and rand(). In which libraries are they declared?

Edited 6 Years Ago by didi00: n/a

#include <iostream> and try it. I hope you actually have a method called int fork();. good luck.

Actually I had the iostream.h, but it says no such file or directory. And I fixed the fork() with <unistd.h>. So my problem still are srand(), rand() and cout (even though I don't know why it makes problem for cout).

Edited 6 Years Ago by didi00: n/a

why are you making it to be iostream.h?...just make it iostream. i believe the .h is not used anymore. but i might be a little off. in any case, just using the iostream should be good enough. also, include this. #include <cstdlib> and see how it works. out. i suggest you also find libraries that dont use the .h extension.

Great, it did the trick. Now the error is:

in function main:
undefined reference to 'getmem(int)'
ld returned 1 exit status

What's the trick with getmem()? How to fix this? Thanks!

Edited 6 Years Ago by didi00: n/a

because you have declared it as extern...and i dont see you including any external .cpp files here. remove the extern and test it.

Nope, the error is still the same. Any other ideas? Please?
Here is the full error code:

in function 'main':
project1.cpp:(.text + 0x22): undefined reference to 'getmem(int)'
collect2: ld returned 1 exit status

Ok, how can I define getmem()? And where?
Sorry for the stupid questions but I just started programming with Linux.

well actually im gonna say he has it defined...but its not doing anything. its a empty method. looks like you just got this code from somewhere. understand what you need to do first and then research about it. look at this site and see what getmem() does and see if you really need it or you can use something else

http://www.codeguru.com/cpp/tic/tic0202.shtml

Yeah I tried malloc(), it doesn't show any errors now but the files that the program should output (F1.txt and F2.txt) are nowhere to be seen. I changed this:

char* malloc();
 
int main(){
	int ID=0, nID, status=0;
	int i;
	short *a=(short*)malloc(3271);
	FILE *f;
	srand((unsigned)time(NULL));

Help anyone please?

Edited 6 Years Ago by didi00: n/a

What is this 3271. In the current form you are allotting 3271 bytes of memory. Is that what you want ?Also after malloc you have to check to see if the memory has been allotted or not

With regards to the file. Where are you opening and closing the files ?

Edited 6 Years Ago by abhimanipal: n/a

Well, I don't know. I thought maybe 3271 bytes will be enough for 50 random numbers. But I think that maybe I need twice more.
How can I check if the memory has been alloted? (sorry I'm new to this function and Linux).
My files are in home directory.

You think you need 3271 bytes for 50 numbers that are most likely 2 bytes each?
And exactly what is wrong with short* a=new short[50]; ?

In one of my previous posts I told you to google for the syntax of malloc. Did you do that ?Both of your questions will be answered.

I meant where in the main program are you opening and closing the files ?Also is it necessary for you to use processes or can you use threads as well ?

I don't know, I mean they're random nubers and I can't possibly know how much bytes I'll need for 50 of them. And it's better to have more, tahn less :-). Yes I googled it, but I didn't understand it very well. And yes I have to use processes (unfortunately). Well actually everything happens in the main program. The opening and closing is under the comment //The processes:

#include<fcntl.h>
#include<wait.h>
#include<stdio.h>
#include<time.h>
#include<unistd.h>
#include<iostream>
#include<cstdlib>
using namespace std;

char* malloc();

int main(){
	int i;
	int ID=0, status=0, numID;
	short *buf=(short*)malloc(3271);
	FILE *f;
	srand((unsigned)time(NULL));
	// Defining the processes
	cout<<"Process A is starting...\n";
	ID++;
	numID=fork();
	if(numID<0){
		cout<<"Error!\n";
		return 0;
	}
	else if(numID!=0){
		wait(&status);
		cout<<"Process B is starting...\n";
		ID++;
		numID=fork();
		if(numID<0){
			cout<<"Error!\n";
			return 0;
		}
		else if(numID!=0){
			cout<<"Process C is starting...\n";
			ID++;
			numID=fork();
			if(numID<0){
				cout<<"Error!\n";
				return 0;
			}
			else if(numID!=0)
				ID=0;
		}
	}
	// The processes
	if(ID==1)
		for(i=0; i<50; i++){
			*(buf+i)=rand();
		}
	if(ID==2){
		f=fopen("F1.txt", "w");
		if(f==NULL)
			cout<<"Error! File 1 was not created\n";
		for(i=0; i<50; i++){
			if((*(buf+i)%2)==0)
				fprintf(f, "%i\n", *(buf+i));
		}
		fclose(f);
	}
	if(ID==3){
		f=fopen("F2.txt", "w");
		if(f==NULL)
			cout<<"Error! File 2 was not created\n";
		for(i=0; i<50; i++){
			if((*(buf+i)%2)!=0)
				fprintf(f, "%i\n", *(buf+i));
		}
		fclose(f);
	}
	wait(&status);
	return 0;
}

And yes maybe short* buf=new short[50]; will be simpler, but still no .txt files.

Edited 6 Years Ago by didi00: n/a

I don't know, I mean they're random nubers and I can't possibly know how much bytes I'll need for 50 of them.

Not sure why you think that, but each variable of a certain type needs the same amount of memory. For char, it's usually 1 byte, short is usually 2 bytes wide, int 4 bytes and so on.

If you want to share these numbers between the processes, you will have to use mmap, because otherwise, when you assign these numbers in process A, they won't carry over to the other processes.

mmap? Can you show me with little code please? Also the thing is the .txt files are not created at all. Should I put every process in different function? Will it work then or that's just waste of time? I mean I've tried it but no luck so far :-(

Edited 6 Years Ago by didi00: n/a

If there just need to be three processes in total (including the original one), you can do it this way (process B being the original one):

#include <iostream>
#include <sys/wait.h>
#include <sys/mman.h>
#include <fcntl.h>

using namespace std;

static int errorMessage()
{
  cout << "Error." << endl;
  return 1;
}

int main()
{
  int zfd=open("/dev/zero",O_RDWR);
  if (zfd==-1)return errorMessage();

  const int numberCount=50;
  short* numbers=(short*)mmap(0,sizeof(*numbers)*numberCount,PROT_READ|PROT_WRITE,MAP_SHARED,zfd,0);

  cout << "Starting process A..." << endl;
  int ret=fork();
  if (ret<0)return errorMessage();
  int ID;
  if (ret==0)ID=1;
  else
  {
    int status;
    wait(&status); //wait for A to terminate
    cout << "Starting process C..." << endl;
    int ret=fork();
    if (ret<0)return errorMessage();
    if (ret)ID=2;
    else ID=3;
  }
  if (ID==1) //process A
  {
  }
  if (ID==2) //process B
  {
  }
  if (ID==3) //process C
  {
  }
}

It shows how to use mmap. You should also search http://linux.die.net using Google whenever you need to know how to use a particular function.
Don't use fopen/etc. to write to files - those are C functions. Use ofstream instead.

Edited 6 Years Ago by Aranarth: n/a

Oh my... I can't make it work. Maybe I should just give up... I haven't sleep all night for this thing, and in about 2 hours I should go and give the task. I'm so frustrated!

Yeah... I can't make it. I should just give up. I haven't sleep all night for this thing and I can't think straight. The stupid part is that in about 2 hours I should go and give it. This is so frustrating...

Edited 6 Years Ago by didi00: n/a

What's the problem? I gave you a template to work with, you just need to insert the process code snippets - and you already have those.

Edited 6 Years Ago by Aranarth: n/a

It's just I can't make the ostream work. Now everything is confusing. I'm mixing C and C++ codes.

Okay then.
That's how you use ofstream:

#include <iostream>
#include <fstream>
#include <sys/wait.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <cstdlib>

using namespace std;

static int errorMessage()
{
    cout << "Error." << endl;
    return 1;
}

int main()
{
    int zfd=open("/dev/zero",O_RDWR);
    if (zfd==-1)return errorMessage();

    const int numberCount=50;
    short* numbers=(short*)mmap(0,sizeof(*numbers)*numberCount,PROT_READ|PROT_WRITE,MAP_SHARED,zfd,0);

    cout << "Starting process A..." << endl;
    int ret=fork();
    if (ret<0)return errorMessage();
    int ID;
    if (ret==0)ID=1;
    else
    {
        int status;
        wait(&status); //wait for A to terminate
        cout << "Starting process C..." << endl;
        int ret=fork();
        if (ret<0)return errorMessage();
        if (ret)ID=2;
        else ID=3;
    }
    if (ID==1) //process A
    {
      srand(time(0));
      for (int i=0;i<numberCount;i++)numbers[i]=rand();
    }
    if (ID==2) //process B
    {
      ofstream file("F1.txt",ios::trunc);
      for (int i=0;i<numberCount;i++)if (numbers[i]%2==0)file << numbers[i] << endl;
    }
    if (ID==3) //process C
    {
      ofstream file("F2.txt",ios::trunc);
      for (int i=0;i<numberCount;i++)if (numbers[i]%2!=0)file << numbers[i] << endl;
    }
}

Thank you so much!!! THANK YOU!!!
I was just giving my last shot in C with Dekker or Peterson algorithm, because I'm better at C, but I'll give your code a try.
THANK YOU AGAIN!!!

Oh... again it compiles with no errors but it doesn't output F1.txt and F2.txt. At least I've learned something new in C++.

You're just looking for the files in the wrong place.
They will be created inside the current working directory, i.e. in the directory you execute the program from.

Edited 6 Years Ago by Aranarth: n/a

I execute the .cpp in home directory, my .cpp file is also there, I checked with pwd I'm in home directory. I also searched them, but no. It's ok though, maybe something's wrong with my kubuntu.

This question has already been answered. Start a new discussion instead.