There are times when a resource manager isn't required.
The most obvious case would be if a program doesn't need to receive messages. But still, if your program is event-driven, you might want to look at using the dispatch library to handle internal events. In the future, if your program ever needs to receive messages, you can easily turn it into a resource manager.
Another case might be if your program interfaces only with its children. The parent has access to all the children's information required to interface with them.
Nevertheless, you can turn almost everything into a resource manager. If your resource manager's client uses only the POSIX API, there's less documentation to write, and the code is very portable. Of course, in many cases, providing an API on top of the POSIX API is often very desirable. You could hide the details of devctl() or custom messages. The internals of the API could then be changed if you have to port to a different OS.
If you must transfer high volumes of data at a very high rate, a resource manager can be a problem. Since resource managers basically interface via IPC kernel primitives, they're slower than a simple memcpy(), but nothing prevents you from using a mix of shared memory, POSIX API, and custom messages, all to be hidden in your own API. It wouldn't be too difficult to have the API detect whether or not the resource manager is local and to use shared memory when local and IPC when remoteāa way to get the best of both worlds.