-1

The code :

for ( ii = 0; ii < 24; ++ii) {

    switch (fork()) {

        case -1 : {
                printf("\n\nproblem with fork() !!! \n\n");
                exit(0);
                };

        case 0 : {
                WriteOnShared_Mem(ii);
                }break;
        default : {
                ChildPidTab[ii] = p;
                usleep(50000);
                ReadShared_MemMp(nbSect, 24,ChildPidTab);
                };
    }
}

My problem is that i get too many child (nbenfant = 24), i got much more than 24 :/

This is my 3rd post today here but still not solved :(

Thanks

D3fman
  • 85
  • 2
  • 11

3 Answers3

1

It's because each child continues with the loop and so in turn fork their own children. When the children are done, you should either return from the main function or call exit.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • yes the problem is that i can't use the exit() bcz it will kill the children and I need 24 child running at once :/ Those r the instruction. – D3fman Aug 31 '13 at 15:02
  • 1
    @shubha The `exit` call just exits the *current* process, not its parent or sibling processes. – Some programmer dude Aug 31 '13 at 15:04
  • yes, if I do exit on the children it will kill them but i don't want that i just want 24 children running at the same time. Is that possible ? – D3fman Aug 31 '13 at 15:05
  • 1
    @shubha You really can't guarantee that with a multitasking system. What do you want to happen if the function you call `WriteOnShared_Mem`) returns before all child processes has been created? It seem you want some synchronization to make sure all processes are running before you continue with that function? – Some programmer dude Aug 31 '13 at 15:09
  • yes thats why i use semaphore, when i do the WriteOnShared_Mem() i do +1 on the semaphore value, and in the function ReadShared_MemMp of the parent, this one will be activected only if semaphore value = 24 (the number of children who wrote on the shared Memory) – D3fman Aug 31 '13 at 15:21
  • 1
    @shubha Ok, then the problem is when the `WriteOnShared_Mem` function *returns*, in that the children continue the loop! After the function returns you *must* exit from the process. – Some programmer dude Aug 31 '13 at 15:22
  • aaah yes i know that i need to stop the child but i can't use the exit() bcz it will kill the child and i won't have concurrency anymore (it is asked on the instruction). So i tried to use break and pause but didn't work :( – D3fman Aug 31 '13 at 15:26
  • @shubha When the child is done, it's done. Why do want to keep the child process running idle even after it's done? If you want to call the function multiple times then have a loop in that specific case, and when the child is done then call `exit`. It's as simple as that. – Some programmer dude Aug 31 '13 at 15:31
  • ok I didn't explain clearly sorry, so the main point of this program is to integrated concurrency/synchronisation. So i need to have multiple process running at the samme time :/ And i could use the thread but i already started with the fork() so .... – D3fman Aug 31 '13 at 15:38
1

Read carefully the fork(2) man page. Read that page several times, it is hard to understand. Read also the wikipage on fork (system call) and on processes (computing).

Please understand -and that takes time- that fork is returning simultaneously twice on success: once in the parent and once in the child

The fork syscall can fail (and then returns -1) for a number of reasons. On failure of fork please use perror or some other way to show the errno. And you should always keep the result of fork. So code

for (ii = 0; ii < 24; ++ii) {
 fflush(NULL);
 pid_t p = fork();
 switch (p) {
    case -1 : // fork failed 
            printf("\n\nproblem with fork() in pid %d error %s!!! \n\n",
                   (int) getpid(), strerror(errno));
            exit(EXIT_FAILURE);
            break;
    case 0: // child process
            WriteOnShared_Mem(ii);
            ii = MAX_INT; // to stop the for loop
            break;
    default: // parent process
            ChildPidTab[ii] = p;
            /// etc.... some synchronization is needed
            break;
    }

In particular, fork can fail because

   EAGAIN fork() cannot allocate sufficient memory to copy the
          parent's page tables and allocate a task structure for 
          the child.
   EAGAIN It was not possible to create a new process because the
          caller's RLIMIT_NPROC resource limit was encountered.  To
          exceed this limit, the process must have either the
          CAP_SYS_ADMIN or the CAP_SYS_RESOURCE capability.
   ENOMEM fork() failed to allocate the necessary kernel structures
          because memory is tight.

If you want to be able to fork more processes, try to:

  • increase the RLIMIT_NPROC resource limit with setrlimit(2) (which might be called by system facilities, so look also into /etc/pam.d/login etc

  • lower the resources required by the fork-ing program. In particular, lower the heap memory requirements

  • increase some system resources, like perhaps swap. You could swapon some temporary file for testing.

As Joachim Pileborg replied you should avoid forking too much (the forked process continues the loop so is also forking again).

Don't forget that stdio routines are buffered. Use fflush(3) appropriately.

I suggest reading the Advanced Linux Programming book (available online) which has a full chapter explaining process handling on Linux.

BTW, check with ps or top or pstree how many processes you have (and with the free command how much memory is used, but read http://linuxatemyram.com/ before complaining). It could happen that your particular system is not able to fork more than 24 times your particular program (because of lack of resources)

Study also the source code of simple shells (like sash) and use strace -f (e.g. on some shell, or on your program) to understand more what syscalls are done. Also learn how to use the gdb debugger.

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • I just want my 24 child but they need to be running at the same time. – D3fman Aug 31 '13 at 15:04
  • "forking too much" how i just did one fork :( – D3fman Aug 31 '13 at 15:06
  • ok thanks for the correction for the fork() error but i can't check it because there is no error when i do the fork() -_- – D3fman Aug 31 '13 at 15:23
  • Please take several hours to read tutorials and linked resources. You have some fundamental misunderstandings. You need to learn a lot more. And add more `printf` and `fflush` calls for debugging purposes. – Basile Starynkevitch Aug 31 '13 at 15:30
  • yes sir i know, I'm still a student and learning each day but when i don't get something i come ask to others like you :) – D3fman Aug 31 '13 at 15:35
  • But asking is less efficient than learning, and learning requires time (and reading and experimenting). – Basile Starynkevitch Aug 31 '13 at 15:35
1

The child process coutinue fork new child process, you just need stop it .

Like this:

 switch (fork()) {

    case -1 : {
            printf("\n\nproblem with fork() !!! \n\n");
            exit(0);
            };

    case 0 : {
             i = 24 ;                 //--- here I set i = 24 , so child process will stop fork new child process.
            WriteOnShared_Mem(ii);
            }break;
    default : {
            ChildPidTab[ii] = p;
            usleep(50000);
            ReadShared_MemMp(nbSect, 24,ChildPidTab);
            };
    }
}
Lidong Guo
  • 2,817
  • 2
  • 19
  • 31