LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-12-2003, 04:48 PM   #1
Avatar33
Member
 
Registered: May 2003
Location: South Africa
Distribution: Ubuntu
Posts: 75

Rep: Reputation: 15
Question Fork again


Hi all.
I know that there have been many posts on forks, but none of them answer my question exactly. I know that a fork starts another process, but where exactly does the new process start running its code? After the fork? At the beggining of the program?

I wrote a program that looks like this.

//headers

int main()
{
for(char i='a';i<=z;i++)
{
cout<<i;
if(i=='m')
fork();
}
return 0;
}

What I expected the prog to do was produce: "abc...mmnnooppqq..." but instead I got "abcde...xyzabcde...xzy". Does this mean that the process gets started from the beggining of the code or is there some other reason for this behaviour.

Thanks Again
 
Old 08-12-2003, 05:16 PM   #2
kev82
Senior Member
 
Registered: Apr 2003
Location: Lancaster, England
Distribution: Debian Etch, OS X 10.4
Posts: 1,263

Rep: Reputation: 51
whoa, that worried me for a while. try the following instead
Code:
int main()
{
    for(char i='a';i<='z';i++)
    {
        sleep(1);
        cout<<i<<flush;
        if(i=='m') fork();
    }
    return 0;
}
what was happenning was, in the time it takes for the fork to copy its data to form the second process(fork is not very fast) the first process had finished. as for why it started at a again im not sure but i think its a related problem.

as the man page says, the new process starts at the return from the fork() and the value returned can be used to determine if you are in the child or not.

Last edited by kev82; 08-12-2003 at 05:17 PM.
 
Old 08-15-2003, 03:52 PM   #3
Avatar33
Member
 
Registered: May 2003
Location: South Africa
Distribution: Ubuntu
Posts: 75

Original Poster
Rep: Reputation: 15
not yet

Thanks kev for the reply, but still no luck. The only difference is that the output takes really long to display and it always displays the output all at once ie "abc..." for the parent process and then "abc..." for the child process a while later.
I'm running Redhat 8.0 and compilling and running the programs in the terminal. Could this have any affect? I'm currently in windows so I can't test it now. Can someone at least tell me if the above program works on there system. Thank you again.
 
Old 08-15-2003, 04:21 PM   #4
kev82
Senior Member
 
Registered: Apr 2003
Location: Lancaster, England
Distribution: Debian Etch, OS X 10.4
Posts: 1,263

Rep: Reputation: 51
it works on mine, your flush isnt working properly. replace cout<<i<<flush; with cerr<<i; that should work as cerr is not buffered. if it doesnt then im really confused, try it on someone elses machine.
 
Old 08-15-2003, 05:04 PM   #5
esben
Member
 
Registered: Jun 2003
Location: Copenhagen, Denmark
Distribution: Gentoo
Posts: 48

Rep: Reputation: 15
Hey, you had me intrigued for a while, too. What I think is happening is this:

cout is buffered, so somewhere there is a buffer. Now, looping until you get to fork is not enough to flush the buffer, so the buffer will contain

"abcdefghijklm"

Now, when you fork, this buffer will be forked, too. So when both loops proceeds in either process, they will both append to their own copy of the above buffer, and will thus produce identical output when the buffer is flushed at process end. The timing or speed of fork has nothing to do with it; it's all a matter of buffering. As kev82 writes, using cerr instead of cout will probably elminate this problem -- flushing the buffer before fork will (tested).

Here's my version of the testing program:
#include <unistd.h>
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
cout << ((argc>1)?"Flush before fork":"Not flush before fork") << endl;
for (char i = 'a'; i <= 'z'; i++) {
cout << i;
if ('m' == i) {
if (argc>1)
cout << flush;
fork();
}
}
cout << endl;
sleep(1);
return 0;
}


And a testrun:

esben ~/c++/diverse $ ./fork
Not flush before fork
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
esben ~/c++/diverse $ ./fork 5
Flush before fork
abcdefghijklmnopqrstuvwxyz
nopqrstuvwxyz
esben ~/c++/diverse $
 
Old 08-15-2003, 05:25 PM   #6
kev82
Senior Member
 
Registered: Apr 2003
Location: Lancaster, England
Distribution: Debian Etch, OS X 10.4
Posts: 1,263

Rep: Reputation: 51
esben is correct about fork copying the buffer, that explains why a,b etc appear twice, i hadnt considered that. you still have the problem that your flush doesnt work though, so you should try using cerr to see what happens.
 
Old 08-15-2003, 10:22 PM   #7
dharmender_rai
Member
 
Registered: Aug 2002
Location: Pune,India
Posts: 39

Rep: Reputation: 15
Hi,
Try outputing the result with the pid of the process. In that way you would be knowing which process has generated what.

--Dharmender Rai
 
Old 08-16-2003, 10:11 AM   #8
Avatar33
Member
 
Registered: May 2003
Location: South Africa
Distribution: Ubuntu
Posts: 75

Original Poster
Rep: Reputation: 15
Wow, not bad at all. Thank you all. It works almost perfectly. Sorry Kev I misread your first post and forgot to flush Here is the full code
using namespace std;
int main()
{
int pid;
for(char i='a';i<'z';i++)
{
cout<<i<<flush;
if(i=='m')
{
pid=fork();
if(pid!=0)
{
sleep(7);
}
}
sleep(1);
}
if(pid!=0)
{
cout<<"The id of the child process is "<<getpid()<<endl;
}
else
{
cout<<"The id of the parent process is "<<getpid()<<endl;
}
if(pid!=0)
{
cout<<"Press a key to exit"<<endl;
getchar();
}
return 0;

A few more qeustions if you guys have any patience left .
1) I want the program to print "abc...mmnnoo.....zz" so I have a problem with timing. Any suggestions?
2) When both processes have finished printing the alphabet , the parent process must wait for the child process to finish, then print its ID and then quit. I must use the wait() command for this,right? I can't "man wait", am I missing files or are there no man pages for wait()
3) When did gcc start using namespaces and is there a way to disable them?
 
Old 08-16-2003, 11:01 AM   #9
kev82
Senior Member
 
Registered: Apr 2003
Location: Lancaster, England
Distribution: Debian Etch, OS X 10.4
Posts: 1,263

Rep: Reputation: 51
1) my program in post 2 does exactly that.
2) there are man pages for wait() and waitpid(), you should have them installed, you can get them from your local kernel.org mirror.
3) probably since they became a part of the C++ standard, but possibly before. no you cant disable them, why would you want to?

<edit> please use code tags, it makes is ALOT easier to read your code
 
Old 08-16-2003, 11:27 AM   #10
esben
Member
 
Registered: Jun 2003
Location: Copenhagen, Denmark
Distribution: Gentoo
Posts: 48

Rep: Reputation: 15
Quote:
Originally posted by Avatar33
A few more qeustions if you guys have any patience left .
1) I want the program to print "abc...mmnnoo.....zz" so I have a problem with timing. Any suggestions?
2) When both processes have finished printing the alphabet , the parent process must wait for the child process to finish, then print its ID and then quit. I must use the wait() command for this,right? I can't "man wait", am I missing files or are there no man pages for wait()
3) When did gcc start using namespaces and is there a way to disable them? [/B]
1) Well, you could use a pipe to synchronize the two, if you want. Another way is to create a socketpair. See main 2 pipe and man socketpipe. But what's the purpose? It seems to be a very complicated way to print a few letters
2) I can cetainly man wait. There's plenty of internet sites carriying the full linux man pages, so google is another way. Using wait or waitpid is the way to wait for the child to finish, yes.
3) Dunno about disabling, but "info gcc" (or man gcc if you prefer) will certainly answer that one. But remember: namespaces are there for a very good reason. Why disable them?
 
Old 08-16-2003, 08:40 PM   #11
dharmender_rai
Member
 
Registered: Aug 2002
Location: Pune,India
Posts: 39

Rep: Reputation: 15
Hi,
[1] First of all please do not use gcc for C++ programs. Although it compiles them still you should use g++ that is a wrapper on gcc for CPP programs.
as far as the namespace thing is concerned, if you use iostream.h (header file) instead of iostream (it is a wrapper on former and is called a package not a header), then you would not need writing namespace.

[2] as there are two separate processes, and there turn is decided by the os schedular, please do not take the risk of assuming the output sequence.

-- Dharmender Rai
 
Old 08-17-2003, 05:07 AM   #12
kev82
Senior Member
 
Registered: Apr 2003
Location: Lancaster, England
Distribution: Debian Etch, OS X 10.4
Posts: 1,263

Rep: Reputation: 51
Quote:
Originally posted by dharmender_rai
Hi,
if you use iostream.h (header file) instead of iostream (it is a wrapper on former and is called a package not a header), then you would not need writing namespace.
you should not use iostream.h, it is limited to char based streams and it has a different interface than iostream. if you want to get rid of namespaces just put 'using namespace std;' at the start of your program and you can forget about them.
 
Old 08-19-2003, 09:36 AM   #13
DIYLinux
Member
 
Registered: Jul 2003
Location: NL
Distribution: My own
Posts: 92

Rep: Reputation: 18
I think i am missing the point of this thread; why do you expect the output of the two processes to be synchronised when you do not use any synchronisation primitives (mutexes, semaphores) ?

The output of the program in the original question is perfectly allright. On a uniprocessor system with a non-preemptive kernel (linux 2.4 i presume) context switches between parent and child may occur when you call a system (s. manpages, section 2) function. Then again, it may not consider giving the cpu to the child process before the parent terminates.

The flush method suggested is not guaranteed to work. A C++ library is allowed to pass a buffer on to an underlying userspace buffering solution, like C's stdio, so the kernel still wont know about the new output, and no system call, and therefore no context switch will take place.
 
Old 08-22-2003, 01:41 PM   #14
Avatar33
Member
 
Registered: May 2003
Location: South Africa
Distribution: Ubuntu
Posts: 75

Original Poster
Rep: Reputation: 15
Lightbulb

Thanks for all the replies, you have all been a great help.
1) The reason that I want to disable namespaces is that gcc on the universities computers does not use them and it will make it easier for me to have working code on the universities computers if I don't use namespaces.
2) The point of the program is to help me learn.
3)
Quote:
as there are two separate processes, and there turn is decided by the os schedular, please do not take the risk of assuming the output sequence.
I agree with this statement so I will use pipes to synchronize my programs.
It seems I've solved all my problems for now, thanks to you guys.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
more on fork() feetyouwell Programming 6 09-17-2004 11:18 AM
fork beginner_84 Programming 2 08-20-2004 04:53 AM
fork() vibhory2j Linux - Software 1 05-24-2004 04:11 AM
fork() lowlifeish Programming 3 11-04-2002 10:50 AM
Fork Ztyx Linux - General 1 08-31-2002 11:25 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 11:53 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration