Find the answer to your Linux question:
Page 1 of 2 1 2 LastLast
Results 1 to 10 of 11
I am new to linux programming. I studied about the fork call in my course on unix operating systems. So I tried to implement signals and fork calls in a ...
  1. #1
    Just Joined!
    Join Date
    Oct 2011
    Posts
    5

    How to fork in linux?

    I am new to linux programming. I studied about the fork call in my course on unix operating systems. So I tried to implement signals and fork calls in a program, Its source is as follows:

    Code:
    #include<stdio.h>
    #include<sys/ipc.h>
    #include<signal.h>
    #include<stdlib.h>
    
    void interrupt_0(void);
    
    int main(void)
    {
      int i=0,ppid,j=0;
      void (*interrupt)(void); //fuction pointer
      //interrupt = interrupt_0;
      interrupt = interrupt_0;//initialized to point interrupt_0()
      
      int id=fork();
      printf("\n%d",id); //display the received pid
      
      if(id==0)//enter child process
      {
        printf("\n In child Process");
        ppid=getppid();
         while(i<10000) //To generate delay
          i++;
        i=0;
        while(i<10000) //To generate delay
          i++;
         //sleep(5);
    
        if(kill(ppid,SIGUSR1)==-1) //Send Signal to                      
          exit(-1);                     //the parent process
        exit(0);
      }
      else //enter parent process
      {
        signal(SIGUSR1,interrupt);
        printf("\nIn Parent Process");
        pause(SIGUSR1); //wait up till signal occours
        printf("\nDone");
      }
      return 0;
    }
    
    void interrupt_0(void)//Signal Catcher
    {
      printf("\n Signal Received\n");
    }
    But it did not give proper output as expected. I think I did a few steps wrong. So can anybody tell me how to use signal and fork calls in linux. I am using Kubuntu 10.04 on virtual machine.

    O/P:
    In Parent Process
    Signal Received

    Done
    In Child Process

    (Then the terminal hangs in infinite loop)

    Thanks in advance.
    Last edited by MikeTbob; 10-29-2011 at 10:44 AM. Reason: Added Code Tags

  2. #2
    Just Joined!
    Join Date
    Apr 2010
    Posts
    66
    I am not a programmer, but isn't this an infinite loop?

    Code:
    ...
    while(i<10000) //To generate delay
    i++;
    i=0;
    ...
    
    N
    Last edited by MikeTbob; 10-29-2011 at 10:45 AM. Reason: Added Code Tags

  3. #3
    Linux Newbie
    Join Date
    Nov 2008
    Location
    Tokyo, Japan
    Posts
    243
    First, you commented-out "sleep(5)" and replaced it with while loops to "generate delay". This will not work, you must use "sleep(x)".

    Second, this code makes no sense:
    Code:
    if(kill(ppid,SIGUSR1)==-1) { //Send Signal to 
    	exit(-1); //the parent process
    	exit(0);
    }
    It is meaningless to have two "exit()" calls in a row.

    I think you misunderstand "fork()". Perhaps you believe calling "exit(-1)" will end the child process and go back to the parent process, then the parent process will call "exit(0)"? This is incorrect.

    Fork does not create a child process "inside" of the parent processes. Calling "exit()" will NOT return program flow to the parent process. The child process is created by the operating system by making an exact copy of the parent process in memory. The only thing that is different about the child copy is that the the operating system writes 0 (zero) to the "id" variable in the memory of the child process. Once the child process is created, it is treated like a completely separate program, but identical to the parent and it keeps running normally from after the "fork()" system call, just like the parent process. Calling exit in the child will simply end the child program, nothing happens to the parent. Calling "exit()" twice in a row will have the first "exit()" end the program, the second "exit()" call will never occur.

    In Linux/UNIX systems, what happens when you run program like "firefox" within a shell, like Bash, or the Gnome desktop environment? The parent program (Bash, or Gnome) calls "fork()" and code in the child process does this:
    Code:
    int p_id = fork();
    if(p_id == 0) { exec("firefox"); }
    Fork copies the shell process, Bash or Gnome. Then since the exec() system call occurs in the child, the current child process (which was a copy "Bash" or "Gnome") is deleted and replaced with the "firefox" program. The parent processes does not know this happens. No signals are sent to the parent until the child process calls "exit()" or an error occurs. The child with the new "firefox" program in memory now runs normally as the firefox program. What happens next, whether the parent waits for a SIGCHLD signal from the firefox process, or whether the parent continues with firefox running separately, that is up to you, the programmer.

    Also, you should not use SIGUSR1 to communicate between parent and child. You must use the "pipes" API to have child/parent processes communicate with each other. Whenever you use "fread()" and "fwrite()" API to place information into a pipe, the operating system automatically sends signals between the processes, and each program automatically handles the signals with their default signal handler, and automatically buffers the data transfer. Signals are difficult to work with, and you shouldn't ever have to worry about it because the Pipes API does it for you.

  4. #4
    Just Joined!
    Join Date
    Oct 2011
    Posts
    5
    I had initialized i when i declared it. See the statement int i=0,pid,j=0;

  5. #5
    Just Joined!
    Join Date
    Oct 2011
    Posts
    5
    ramin.honary: Thanks for your reply. The two exit calls given there were for my later use. It indicated exit codes which will be returned to the parent process and I will check them in the parent process. I hadn't written that code yet but will write it in future. I know that fork will not return to the parent process after calling of exit. My question was why did my child process hang up in an infinite loop, and if it hanged up in any of my above generated while loops then how come signal SIGUSR1 was raised by the kernel? And thanks for the information given by you. It will help me in future to learn good c programming in linux. I saw such kind of code in my book and was just testing for working of signals. I am studying about pipes and messages currently and would soon implement them.
    Thanks for your reply.

  6. #6
    Linux User sgosnell's Avatar
    Join Date
    Oct 2010
    Location
    Baja Oklahoma
    Posts
    358
    In this case it really makes no difference, but do not depend on initializing variables in main() and expect them to still have the same value each time they're used in a function. The function can change the value and it will be left as it is. Give the variable the value you want in the function, or otherwise check its value before using it. Sleep() is the way to go to get a delay, because you have no idea how long it will take to increment an integer, other than it won't take very long at all. A CPU operating at 1GHz (1,000,000,000 operations/second) takes .00001 second to do your loop, and that's not a fast processor. With sleep() you specify the exact time.

  7. #7
    Linux Newbie
    Join Date
    Nov 2008
    Location
    Tokyo, Japan
    Posts
    243
    Quote Originally Posted by mm2426 View Post
    ramin.honary: Thanks for your reply.... My question was why did my child process hang up in an infinite loop, and if it hanged up in any of my above generated while loops then how come signal SIGUSR1 was raised by the kernel?
    Well, often when a multi-threaded or multi-process program hangs, it is not because of an infinite loop, it is because of a deadlock. Does you program output the same information forever? If so that is an infinite loop. Does the program simply hang without doing anything forever? If so, that is probably a deadlock.

    I believe your problem is the "pause()" statement in the parent process and the "kill()" statement in the child process.

    The parent will wait for a signal, but I believe the child will exit before the signal is sent (maybe because "kill()" failed), so the parent will wait forever. Your child process does not report any error when the "kill()" statement fails, it simply calls "exit(-1)", and so probably the parent waits forever for the child to send a signal but the child has already exited from the failed "kill()" system call. You do not know if the signal is delivered or not.

    But, it is very difficult to see what the program is doing from the code you have written here, I can't really read the code. Try changing your "kill" system call to this:
    Code:
    if(kill(ppid,SIGUSR1)==-1) { //Send signal to the parent process
    	fprintf(stderr,
    		"Child could not send SIGUSR1 signal: %s\n",
    		strerror(errno)
    	);
    	exit(-1);
    }
    Of course you will have to include <string.h> and <errno.h> as well.
    Last edited by ramin.honary; 10-25-2011 at 04:42 AM. Reason: syntax correction

  8. #8
    Just Joined!
    Join Date
    Oct 2011
    Posts
    5
    The Reason I was not using sleep was, when I used sleep the terminal used to hang up for that much of time and then the output of the program would be displayed on the terminal. But I expected first that "In Child Process" will be displayed after that sleep should be executed, up till then in parallel the parent process should print "In Parent Process" and pause until the SIGUSR1 is received to it, after the child wakes up it will signal the parent process using the kill system call, and exit normally returning exit code 0 and the parent process should wake up handle the interrupt display "Signal Received" display "Done" and exit. But the order of the output is as shown above. I couldn't find it out why?

    Thanks for your reply.

  9. #9
    Just Joined!
    Join Date
    Oct 2011
    Posts
    5
    ramin.honary: I tried what you said. I wrote a printf statement there in the if condition if (kill(..)==-1) then printf("Error Occurred: %s ",strerror(errno));, I also replace the while loops with the sleep(5) call, but still the same sequence follows. First the process id's of both the processes are displayed. Then my terminal hangs up for 5 Seconds and then this output is displayed:

    In Child ProcessIn parent Process
    Signal Received.

    I could not even find out that why the two statements "In Child Process" and "In Parent Process" are displayed in the same line? I had given a \n in both the printf statements.

  10. #10
    Just Joined!
    Join Date
    Oct 2011
    Posts
    1
    See the statement int i=0,pid,j=0;

Page 1 of 2 1 2 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •