I want to limit N processes ( introduced as parameters ) at the same time, but there is always more than N files to process. One process per file. Only N processes are being processes at one time. I know what the program must do but don't know how to make it happen.
I am sorry if I don't explain too well, I will answer all details needed. Using C code in FreeBSD
for (int i = 3; i < argc; i++) {
fflush(NULL);
if((pid_son = fork()) < 0){
printf("Error");
exit(-1);
}
else if(pid_son == 0){
}
}
It isn't clear whether you want a limit enforced by the o/s, nor what your code will do if it runs into that limit (if a fork()
call fails). However, you can arrange to run commands until you reach a limit imposed by the programmer or user (rather than the o/s) and then wait for one of those to finish before launching another.
Here is some C code that should work on most POSIX systems. It is available in my SOQ (Stack Overflow Questions) repository on GitHub as file numproc19.c
in the src/so-1974-7644 sub-directory.
numproc19.c
— with comments removed#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include <string.h>
enum { MAX_KIDS = 4 };
enum { DEF_TASKS = 20 };
static _Noreturn void be_childish(int tasknum)
{
srand(getpid());
struct timespec nap = { .tv_sec = rand() % 5, .tv_nsec = (rand() % 1000) * 1000000 };
int millisecs = nap.tv_nsec / 1000000;
printf("PID %5d (PPID %5d): Task %2d - dozing %d.%.3d\n",
getpid(), getppid(), tasknum, (int)nap.tv_sec, millisecs);
nanosleep(&nap, 0);
printf("PID %5d (PPID %5d): Task %2d - done\n", getpid(), getppid(), tasknum);
exit(tasknum);
}
static size_t dead_kid(pid_t corpse, size_t nkids, pid_t *kids)
{
for (size_t i = 0; i < nkids; i++)
{
if (kids[i] == corpse)
{
kids[i] = kids[--nkids];
return nkids;
}
}
printf("PID %5d exited but was not a known child\n", corpse);
return nkids;
}
static int cmp_pid(const void *vp1, const void *vp2)
{
pid_t v1 = *(pid_t *)vp1;
pid_t v2 = *(pid_t *)vp2;
return (v1 > v2) - (v1 < v2);
}
static void print_kids(size_t nkids, pid_t *kids)
{
qsort(kids, nkids, sizeof(kids[0]), cmp_pid);
printf("Kids (%zu):", nkids);
for (size_t i = 0; i < nkids; i++)
printf(" %5d", kids[i]);
putchar('\n');
}
int main(void)
{
pid_t kids[MAX_KIDS];
size_t nkids = 0;
setvbuf(stdout, NULL, _IOLBF, 0);
for (size_t task = 0; task < DEF_TASKS; task++)
{
pid_t pid = fork();
if (pid < 0)
{
fprintf(stderr, "failed to fork(): (%d) %s\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
if (pid == 0)
be_childish(task);
kids[nkids++] = pid;
printf("Kid: %5d; Number of kids: %2zu\n", pid, nkids);
print_kids(nkids, kids);
if (nkids >= MAX_KIDS)
{
int status;
int corpse = waitpid(-1, &status, 0);
if (corpse < 0)
break;
printf("Child %5d exited with status 0x%.4X\n", corpse, status);
nkids = dead_kid(corpse, nkids, kids);
}
}
int corpse;
int status;
while (nkids > 0 && (corpse = waitpid(-1, &status, 0)) > 0)
{
printf("Child %5d exited with status 0x%.4X\n", corpse, status);
nkids = dead_kid(corpse, nkids, kids);
print_kids(nkids, kids);
}
return 0;
}
The be_childish()
function does whatever real work is required. Here, it reports on its existence and sleeps for a random time rough in the range 0-5 seconds. In production code, it would either run a function in the program or a command that does whatever is required.
The main()
function keeps track of which processes it has launched and once it has reached the limit, it waits for a process to finish. It recognizes that it might have children it doesn't know about and handles them cleanly (reports on their termination and continues unphased by their presence).
Kid: 23402; Number of kids: 1
Kids (1): 23402
Kid: 23403; Number of kids: 2
Kids (2): 23402 23403
PID 23402 (PPID 23401): Task 0 - dozing 4.632
Kid: 23404; Number of kids: 3
Kids (3): 23402 23403 23404
PID 23403 (PPID 23401): Task 1 - dozing 1.881
Kid: 23405; Number of kids: 4
Kids (4): 23402 23403 23404 23405
PID 23404 (PPID 23401): Task 2 - dozing 3.130
PID 23405 (PPID 23401): Task 3 - dozing 0.379
PID 23405 (PPID 23401): Task 3 - done
Child 23405 exited with status 0x0300
Kid: 23406; Number of kids: 4
Kids (4): 23402 23403 23404 23406
PID 23406 (PPID 23401): Task 4 - dozing 2.628
PID 23403 (PPID 23401): Task 1 - done
Child 23403 exited with status 0x0100
Kid: 23407; Number of kids: 4
Kids (4): 23402 23404 23406 23407
PID 23407 (PPID 23401): Task 5 - dozing 4.877
PID 23406 (PPID 23401): Task 4 - done
Child 23406 exited with status 0x0400
Kid: 23408; Number of kids: 4
Kids (4): 23402 23404 23407 23408
PID 23408 (PPID 23401): Task 6 - dozing 1.479
PID 23404 (PPID 23401): Task 2 - done
Child 23404 exited with status 0x0200
Kid: 23409; Number of kids: 4
Kids (4): 23402 23407 23408 23409
PID 23409 (PPID 23401): Task 7 - dozing 3.728
PID 23408 (PPID 23401): Task 6 - done
Child 23408 exited with status 0x0600
Kid: 23410; Number of kids: 4
Kids (4): 23402 23407 23409 23410
PID 23410 (PPID 23401): Task 8 - dozing 0.977
PID 23402 (PPID 23401): Task 0 - done
Child 23402 exited with status 0x0000
Kid: 23411; Number of kids: 4
Kids (4): 23407 23409 23410 23411
PID 23411 (PPID 23401): Task 9 - dozing 2.226
PID 23410 (PPID 23401): Task 8 - done
Child 23410 exited with status 0x0800
Kid: 23412; Number of kids: 4
Kids (4): 23407 23409 23411 23412
PID 23412 (PPID 23401): Task 10 - dozing 4.475
PID 23407 (PPID 23401): Task 5 - done
Child 23407 exited with status 0x0500
Kid: 23413; Number of kids: 4
Kids (4): 23409 23411 23412 23413
PID 23413 (PPID 23401): Task 11 - dozing 1.724
PID 23411 (PPID 23401): Task 9 - done
PID 23409 (PPID 23401): Task 7 - done
Child 23411 exited with status 0x0900
Kid: 23414; Number of kids: 4
Kids (4): 23409 23412 23413 23414
Child 23409 exited with status 0x0700
Kid: 23415; Number of kids: 4
Kids (4): 23412 23413 23414 23415
PID 23414 (PPID 23401): Task 12 - dozing 3.973
PID 23415 (PPID 23401): Task 13 - dozing 0.222
PID 23415 (PPID 23401): Task 13 - done
Child 23415 exited with status 0x0D00
Kid: 23416; Number of kids: 4
Kids (4): 23412 23413 23414 23416
PID 23416 (PPID 23401): Task 14 - dozing 2.824
PID 23413 (PPID 23401): Task 11 - done
Child 23413 exited with status 0x0B00
Kid: 23418; Number of kids: 4
Kids (4): 23412 23414 23416 23418
PID 23418 (PPID 23401): Task 15 - dozing 1.322
PID 23418 (PPID 23401): Task 15 - done
Child 23418 exited with status 0x0F00
Kid: 23419; Number of kids: 4
Kids (4): 23412 23414 23416 23419
PID 23419 (PPID 23401): Task 16 - dozing 3.571
PID 23416 (PPID 23401): Task 14 - done
Child 23416 exited with status 0x0E00
Kid: 23420; Number of kids: 4
Kids (4): 23412 23414 23419 23420
PID 23420 (PPID 23401): Task 17 - dozing 0.820
PID 23412 (PPID 23401): Task 10 - done
Child 23412 exited with status 0x0A00
Kid: 23421; Number of kids: 4
Kids (4): 23414 23419 23420 23421
PID 23421 (PPID 23401): Task 18 - dozing 2.069
PID 23420 (PPID 23401): Task 17 - done
Child 23420 exited with status 0x1100
Kid: 23422; Number of kids: 4
Kids (4): 23414 23419 23421 23422
PID 23422 (PPID 23401): Task 19 - dozing 4.318
PID 23414 (PPID 23401): Task 12 - done
Child 23414 exited with status 0x0C00
PID 23421 (PPID 23401): Task 18 - done
Child 23421 exited with status 0x1200
Kids (2): 23419 23422
PID 23419 (PPID 23401): Task 16 - done
Child 23419 exited with status 0x1000
Kids (1): 23422
PID 23422 (PPID 23401): Task 19 - done
Child 23422 exited with status 0x1300
Kids (0):