I saw here (Wikipedia article about IPC) that these are two separate things, but even reading each one's dedicated Wikipedia page I didn't understand what the difference is.
Can someone explain this simply?
Message passing is a very general term. It can be examined from different aspects, one of those is how data is transferred from the sender to the receiver:
Synchronous message passing: the sender and the receiver have to "meet" at their respective send
/receive
operations in order that data can be transferred. This is also called 'rendezvous' or 'handshaking'. This form of transfer is simple, but might be inefficient because the sender may have to wait even if it has done its duty and prepared the data to be sent.
Asynchronous message passing: the sender does not wait for the receiver to reach its receive
operation, rather it gets rid of the prepared data and continues its execution. This form of transfer does not force the sender to wait, but creates another problem: there may be messages that have already been sent but not yet received, and they have to be stored somewhere. This is where message queues come into play, they are the buffers for in-transit messages.
So, the answer to your question is that message queues are used/needed when message passing is done asynchronously rather than synchronously.
As I see it, Message Passing describes a protocol, whereas a message queue is an implementation detail.
Consider the following: Your application has a well defined way to exchange data by passing messages. This means you have implemented a protocol, that describes what messages can be sent and how the application reacts to it. This is what I would call message passing in essence.
Now, you may have implemented this in a number of ways.
A message queue would be a implementation that receives messages of your protocol delivered with message passing and stores them. This makes them available to the internals of your application one by one in the order they arrived. But there is a lot more to it.
So message passing is just a way to say: "I have this instruction or chunk of code that I want to deliver to someone". A program representing a message queue is a receiver of messages and can apply additional logic to it.