Before we get carried away, let's take a look at a couple of examples and see how they abstract some service. We'll look at an actual piece of hardware (a serial port) and something much more abstract (a filesystem).
In this case, the service being provided by the serial resource manager is the capability for a program to send and receive characters on a serial port.
We say that an abstraction occurs, because the client program (the one ultimately using the service) doesn't know (nor does it care about) the details of the UART chip and its implementation. All the client program knows is that to send some characters it should call the fprintf() function, and to receive some characters it should call the fgets() function. Notice that we used standard, POSIX function calls to interact with the serial port.
The service being offered here is the capability for a program to read and write characters on some medium. The abstraction that occurs is the same as with the serial port example aboveāthe client program can still use the exact same function calls (e.g., the fprintf() and fgets() functions) to interact with a storage medium instead of a serial port. In fact, the client really doesn't know or need to know which resource manager it's interacting with.