170 lines
4.7 KiB
Text
170 lines
4.7 KiB
Text
|
IPC - in cinit and in general
|
||
|
=============================
|
||
|
Nico Schottelius <nico-linux-cinit__@__schottelius.org>
|
||
|
0.1, Initial Version from 2006-07-09
|
||
|
:Author Initials: NS
|
||
|
|
||
|
IPC - Inter process communication
|
||
|
|
||
|
Introduction
|
||
|
------------
|
||
|
This document describes the IPC methods used and/or tested for
|
||
|
cinit.
|
||
|
|
||
|
It does not describe in detail, how the different methods work
|
||
|
(this is already done many times, there's great documentation
|
||
|
available online), but more the advantages and disadvantages
|
||
|
(especially for an init system).
|
||
|
|
||
|
What is IPC?
|
||
|
~~~~~~~~~~~~
|
||
|
IPC describes methods to communicate between different processes
|
||
|
(programs).
|
||
|
|
||
|
IPC as described by SUSV3 (The Single UNIX Specification Version 3)
|
||
|
aka IEEE Std 1003.1, 2004 Edition aka POSIX only defines
|
||
|
MSQ, SHM and Semaphores as IPC. This document also covers
|
||
|
Sockets and FIFOs.
|
||
|
|
||
|
|
||
|
What is not (yet) covered by this document?
|
||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
Speed of different IPC methods, different behaviour on different
|
||
|
unices.
|
||
|
|
||
|
|
||
|
Why do you need IPC for an init system?
|
||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
|
||
|
cinit IPC history + analysis
|
||
|
----------------------------
|
||
|
|
||
|
|
||
|
FIFOs
|
||
|
~~~~~
|
||
|
First in - first out
|
||
|
File on the filesystem
|
||
|
Always need two files for two way communication
|
||
|
|
||
|
Hints
|
||
|
^^^^^
|
||
|
The first idea for IPC in cinit was to use two FIFOs, like minit does.
|
||
|
Wrong assumption:
|
||
|
runit also uses fifos, but two fifos for each services. That way
|
||
|
more parallel transmissions is possible.
|
||
|
You have to pay attention: Maximum number of opened files!
|
||
|
(On Linux 2.6 this is 1024, which makes a maximum of 512 services.
|
||
|
This limit is most likely never reached, but you have to keep it
|
||
|
in mind).
|
||
|
|
||
|
Sockets
|
||
|
~~~~~~~
|
||
|
Clean and beautiful. They allow easy two way communication.
|
||
|
|
||
|
If you created a socket, fs is r/o, you cannot use it, although
|
||
|
there is SO_REUSE.
|
||
|
|
||
|
First method: Using memory mapped part (tmpfs).
|
||
|
Second method: use interal communication (pipes!) and external after
|
||
|
/etc/cinit/ becomes writable.
|
||
|
|
||
|
|
||
|
Current IPC configuration
|
||
|
--------------------------
|
||
|
|
||
|
- switchable (conf/ipc_method)
|
||
|
- each ipc implementation needs:
|
||
|
|
||
|
ipc.h -> for global variables and ipc specific things
|
||
|
prefix variables with ipc_
|
||
|
int cinit_ipc_init(void); -> general initialization
|
||
|
return 1 on success, 0 on failure
|
||
|
int cinit_ipc_listen(void); -> begin to listen for messages
|
||
|
int cinit_ipc_send(void *data) -> send data to a client
|
||
|
|
||
|
Abstraction layer: cinit_ipc_*
|
||
|
------------------------------
|
||
|
You can choose or even reimplement ipc code for cinit. You only have to create
|
||
|
a directory below src/ipc/ and create the following necessary functions:
|
||
|
|
||
|
int cinit_ipc_init(void);
|
||
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
Initialise the IPC functions in cinit.
|
||
|
|
||
|
|
||
|
int cinit_ipc_listen(void);
|
||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
Never ending looping function that listens for commands and passes the
|
||
|
retrieved command to read_command().
|
||
|
|
||
|
other
|
||
|
~~~~~~
|
||
|
int cinit_ipc_sclose(void); /* fork of cinit come from outside! */
|
||
|
int cinit_ipc_ssend(void *data); /* send to a client from the server */
|
||
|
void cinit_ipc_destroy(void); /* destroy ipc handler in cinit */
|
||
|
|
||
|
|
||
|
cinit_get_data(int ident, int size, void *data) => read size bytes from client
|
||
|
with ident
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* Functions: in clients
|
||
|
*/
|
||
|
int cinit_ipc_logon(void); /* logon to init (client init) */
|
||
|
int cinit_ipc_connect(void); /* connect to init */
|
||
|
int cinit_ipc_csend(struct cinit_message *data); /* send to the server from a client */
|
||
|
|
||
|
|
||
|
--------------------------------------------------------------------------------
|
||
|
Messages:
|
||
|
|
||
|
struct cinit_question qsn;
|
||
|
struct cinit_answer asr;
|
||
|
|
||
|
question:
|
||
|
|
||
|
answer:
|
||
|
|
||
|
int cinit_send_to(struct cinit_question *data, struct cinit_answer *res)
|
||
|
-> return 0 on ipc errors
|
||
|
|
||
|
--------------------------------------------------------------------------------
|
||
|
enable / disable services:
|
||
|
|
||
|
- send svc
|
||
|
- send flags
|
||
|
|
||
|
- recv return:
|
||
|
CINIT_ASW_SVC_STOPPED: successfully stopped the service
|
||
|
|
||
|
CINIT_ASW_SVC_ERR: failed to stop the service
|
||
|
CINIT_ASW_SVC_WANTS: wants failed
|
||
|
CINIT_ASW_SVC_NEEDS: needs failed
|
||
|
opt contains number of failed services
|
||
|
retriev them from cinit after that
|
||
|
|
||
|
--------------------------------------------------------------------------------
|
||
|
TO SORT:
|
||
|
|
||
|
1. message queues
|
||
|
o clients schreiben rein
|
||
|
o datenpaket gross genug fuer antwort?
|
||
|
|
||
|
2. shared memory
|
||
|
o client kann direkt rauslesen, was gestartet werden muss
|
||
|
o client kann direkt abhaengigkeiten starten, muss diese aber
|
||
|
eintragen
|
||
|
|
||
|
Ausprobieren:
|
||
|
- Mutexe
|
||
|
- Message Queues
|
||
|
-
|
||
|
|
||
|
Ideen:
|
||
|
Message queue
|
||
|
1. Client geht auf die normale
|
||
|
als id = pid (cast!)
|
||
|
dann rueck via anderer queue
|
||
|
|