I have write a program by C and run it in Ubuntu,the main code is follow:
int main(){
pid_t pid=fork();
if(pid==0){
printf("d");
exit(0);
}
else{
printf("a");
sleep(4);
}
}
The question is: why the code sleep(4); run before printf("a");
hope someone can give me a answer,thanks!
It is not. Most probably, printf() buffered its output until a chance to output the buffer (in your case, when the process terminated).
Q: why the code sleep(4) run before printf("a")?
A: printf("a") actually runs BEFORE "sleep(4)", just like you see in the code.
However, it doesn't DISPLAY immediately.
The issue is "buffering".
Look here for more details:
buffering behaviour of stdout in c
http://www.pixelbeat.org/programming/stdio_buffering/
SUGGESTED ALTERNATIVE:
pid_t pid=fork();
if(pid==0){
fprintf(stderr, "d");
exit(0);
}
else{
fprintf(stderr, "a");
sleep(4);
}
The reason is that "stderr" is unbuffered: you'll see the output immediately.
Alternatives to using stderr include calling fflush(stdout) or modifying the stream.
It's not, but it may appear that way. printf puts its output into a buffer that probably only gets flushed after the sleep runs. Try putting a call to fflush(stdout) after the printf, but before the call to sleep.
Related
This question already has answers here:
Why does printf not flush after the call unless a newline is in the format string?
(10 answers)
Closed last year.
Here is my code:
int main(int arg, char *argv[]){
short pid;
if((pid = fork()) == 0){
printf("Child is running\n");
while(1) ;
} else {
printf("Parent is running\n");
}
}
After running this, only "Parent is running" is printed to the console. If I remove the while loop, both statements are printed to the console. Why is the while loop causing the child's print statement to be ignored if it appears before it?
In my case both statements were printing on stdout. I'm using Arch Linux
[tushar#arch Desktop]$ ./main
Parent is running
Child is running
In my case while(1); is being ignored, even after removing that line output is same as mentioned above.
After printing "Parent is running" to the stdout your program exits, and after that "Child is running" is printed to stdout.
I would suggest you to read this article fork() in c. Also use fflush(stdout); By the way I have never used minix.
I'm having a problem with fork running in a function I'm using to create a terminal for a school project.
This function is called to handle the user input when they type in a command:
void handleExternalCommands(char ** arr)
{
pid_t pid;
pid = fork();
printf("pid is ", (long) pid);
if (pid == -1)
{
perror("fork");
exit(EXIT_FAILURE);
}
else if (pid == 0)
{
int status = execvp(arr[0], arr);
printf("im in the child process");
if (status == -1)
{
// error handle
}
}
wait();
}
However, no matter what I type in, I can't actually make it inside of the if statement. If I try to find out what's going on with pid by using:
printf(pid);
I get a segmentation fault error?
Thanks for your help in advance, everyone.
UPDATE:
I've changed the code to what it is above. Printing the pid only happens once and it prints nothing: "pid is "
If the execvp() works, the printf() is never executed. You'd only see the message from printf() if (a) you added a newline to the end and (b) the execvp() failed. (OK: you might see it eventually even without a newline, but the newline is a good idea.)
Move the printf() to before the execvp() and (definitely) add the newline and you should see the information. See also printf() anomaly after fork(), but note you are running into a different consequence of not terminating printf() output with newlines.
As to printf(pid) crashing, you need to read the manual on printf()
and add compiler options so you get told about erroneous use.
You probably need:
printf("PID %d\n", pid);
That assumes that pid_t is sufficiently compatible with int not to run into trouble — a moderately safe assumption, but one which can be avoided by writing:
printf("PID %d\n", (int)pid);
(or use int pid; as the definition). But the key point is that you need to use printf() correctly, and execvp() does not return unless it fails.
I m doing some C program using fork()
But I'm getting unexpected output.
#include <stdio.h>
main(){
printf("\nStart of Program");
fork();
printf("\nEnd of Program");
}
Output:
Start of Program
End of ProgramStart of Program
End of Program
Why do I get this output ?
Output should be this:
Start of Program
End of Program
End of Program
This issue is happening because of buffering.
Quoting this post.
When the output of your program is going to a terminal (screen), it is line buffered. When the output of your program goes to a pipe, it is fully buffered.
The posts also contains line by line explanation.
This is because of printf(), printf is buffering the output and only print when he reaches a '\n', so when reaching printf("\nEnd of Program"); printf() prints the content of the buffer which is "Start of Program".
Because fork() duplicates your stack, printf() buffer is duplicated too.
Try:
#include<stdio.h>
main(){
printf("Start of Program\n");
fork();
printf("End of Program\n");
}
Few things here need to check.
From where it is printing "student". I do not see any where you are printing student in your code.
The ideal output is
Start of Program
End of Program
End of Program
If you are not getting above output I will suspect, when fork executed and child got created probably your standard output print was not complete. Flush or \n as last char in print is a must to complete the print job,
To verify this what you can do is, before fork just use fflush.
Also in printf use \n as last char.
#include<stdio.h>
main()
{
printf("Start of Program\n");
fflush(NULL);
fork();
printf("End of Program\n");
}
Try this and let us know.
when fork is come then new process is created.
so end of program before fork call process and after fork call is printed. so that's logic.
I compiled that code myself, and I get following output:
Start of Program
End of Program
Start of Program
End of Program
Which is correct since fork() spawns exactly the same child process its forked from.
Edit: Thanks to the comments, I found out whats really going on. Fork behaves as expected, but the input buffer is not getting flushed before the child process is executed. I've modified the original code to this:
#include <stdio.h>
main(){
printf("\nStart of Program\n");
fflush(stdout);
fork();
printf("\nEnd of Program\n");
}
And the output now reads:
Start of Program
End of Program
End of Program
Which indicates that indeed, fork() only spawns the child process executing downwards from after the fork() call.
#include<stdio.h>
int main()
{
if (fork())
{
wait();
printf("Now I am showing you ls -l"); // why can't we see this ?
execlp("ls","ls", "-l", 0); //gets printed second
}
else
{
printf("We are in the child process."); // gets printed first
}
}
I have this simple peace of code. My question is why don't we see on the console the first print, in the parent process?
The printf function provides buffered IO. When printing to stdout, as you are here, the buffer will normally get flushed when you print a newline \n, which you have not done, so your string is sitting in a buffer waiting to be printed.
The next thing you are doing is calling execlp. The exec family of functions replace the current process with the new one you have specified. The buffer is lost without ever being flushed, because the whole process is replaced.
If you add \n to the strings you are printing, you will probably see the output.
you have to flush stdout before the execlp.
if you put a \n at the end of the printf (or you call fflush(stdout)) you will get the correct result
In the interactive case, standard output is line buffered by default. And that execlp() will replace its memory image, therefore that output line may be dropped before it is written to console.
Change that print() statement to
printf("Now I am showing you ls -l\n");
to fix this problem.
There is 2 problems with your code:
first you need to flush your outputs, either by adding \n in the strings or by calling fflush(stdout)
But it should be the job of the son to exec(), of course you can always exec in the parent, but this is probably not what you want.
A more common fork/exec sample looks like :
int main() {
if (fork()) { // parent
wait(NULL); // wait his child
printf("Ok, my children finished the job\n");
exit(0);
}
else { // child
printf("We are in the child process.\n"); // gets printed first
printf("Now I am showing you ls -l\n");
execlp("ls","ls", "-l", 0); // never return from this
}
}
In Linux, readline() in an infinite loop repeatdly reads text\n. However, as soon as child processes start printing to the screen, readline no longer reads new lines. Even if I repeatdly press enter, readline() doesn't return.
Anyone know what's wrong?
Code sample as requested:
char* input;
int cpid;
while(1)
{
input = readline(">>>");
strcpy(tempInput, input); //...does some stuff w/ tempInput
//....
cpid = fork();
if(cpid == 0){
printf("..."); printf("...");
execl("ls", "ls", "-l", (char*) NULL); //sample execl parameters
}
else{
//do some stuff...
printf("...");
}
free(input);
}
//readline(">>>") works the first time and doesn't return on subsequent calls
The stacktrace of where the code hangs (forever):
Thread [1] (Suspended : Signal : SIGINT:Interrupt)
__read_nocancel() at ../sysdeps/unix/syscall-template.S:82 0x7ffff78f0490
rl_getc() at 0x7ffff7bc3727
rl_read_key() at 0x7ffff7bc3c90
readline_internal_char() at 0x7ffff7baf25f
readline() at 0x7ffff7baf795
main() at /home/.../.../xxx.c:95 0x4010a1
Edit: This probably sounds like total technobabble to experienced unix developers, but could the child process have somehow 'captured' stdin and fail to release it somehow?
Your child processes, even after exec, still has its standard input connected to your terminal. Either use wait() to wait for the child process to finish, or reopen the child's standard input as /dev/null:
close(STDIN_FILENO) && open("/dev/null", "O_WRONLY");
After you fork(), your child process executes the 2 printf calls, then goes on to execute the while(1) loop, so what you are doing is creating 1 extra process after every newline.
What you need to do, is kill the child immediately after it prints the 2 ellipses (...)
Change your code to this:
if(cpid == 0){
printf("..."); printf("..."); exec(...); exit(0);
}
Bear in mind, exit() is called only if the exec() fails.
Edit:
If you intend to accept input for some kind of command line interpreter, readline isn't a very good option. Its official man page says:
BUGS:
It’s too big and too slow.
I could suggest an alternative way of getting the input string:
char c;
inputString = calloc(0,sizeof(char));
inputLength = 0;
c = getchar();
while(c!='\n')
{
inputString = realloc(inputString,(inputLength+1)*sizeof(char));
inputString[inputLength++] = c;
c = getchar();
}
inputString[inputLength] = '\0';
Now you have the string in inputString & its length in inputLength. You could very well do:
execlp(inputString,inputString,0);
to execute the required functionality.
This piece of code is not working because your call to execl() is failing, therefore the child process will resume at the loop code, which will also be using readline().
You must pass the full path to the executable when using execl(), or use the execlp() variant (which search into PATH environment variable) for it to work.
Even for the simplest syscalls, it's a good practice to always check for their return codes.