I am working on an experimental project (just for fun) and I need a way to control the "rhythm" by which my processes are forked. Basically, I have a program that forks itself without attaching to its children. The child process leads the same program via execl
.
// other includes
#include "hook.h"
int
main()
{
const char* progname = "main";
unsigned int child_i;
pid_t pid;
for (child_i = 0; child_i < 3; child_i )
{
// Does some irrelevant stuff here
hook_take();
pid = fork();
if (pid == 0)
{
execl(progname, progname, NULL);
}
else
{
hook_free();
}
}
return 0;
}
The idea here is to create a tree of process, going like this:
main
|-p0
| |-p00
| | |-p001
| | |-p002
| | |-p003
| |-p01
| | |-p011
| | |-p012
| | |-p013
| |-p02
| | |-p021
| | |-p022
| | |-p023
|-p1
| |-p10
| | |-p101
| | |-p102
| | |-p103
| |-p11
...
This, however, ends up creating too many processes and the systems becomes unstable. That is why I opted for using a shared library (hook.h
) to block processes when a maximum number of processes is reached. Which is the job of hook_take()
and hook_free()
. Which are defined in a separate hook.h
file.
#ifndef HOOK_H
#define HOOK_H
#ifdef __cplusplus
extern "C"
{
#endif
#define MAX_HOOKS 1000
extern unsigned int _hooks_count;
void hook_take();
void hook_free();
#ifdef __cplusplus
}
#endif
#endif /* HOOK_H */
And implemented in hook.c
.
#include "hook.h"
#include <unistd.h>
unsigned int _hooks_count = 0;
void
hook_take()
{
while (_hooks_count == MAX_HOOKS)
{
sleep(1);
}
_hooks_count ;
}
void
hook_free()
{
if (_hooks_count > 0)
{
_hooks_count--;
}
}
hook.c
is compiled as a shared library and dynamically linked to the main program.
After some research, I quickly realized that this is not going to work. Because each process will create his own copy of variable _hooks_count
.
What would be the easiest way to solve this problem, without going through too much trouble? Keep in mind that this is just an experiment project and my code need not be enterprise grade or anything.
CodePudding user response:
There are numerous ways to implement interprocess semaphores on Linux. Arguably POSIX semaphores is the easiest:
#define SNAME "/tmp/hook_count"
// PLEASE CHECK ALL ERROR CODES !!!
// In root process
sem_t *sem = sem_open(SNAME, O_CREAT, 0644, MAX_HOOKS);
// In child process after fork
sem_t *sem = sem_open(SEM_NAME, 0);
sem_wait(sem);
// In child process before exit
sem_post(sem);