View
2
Download
0
Category
Preview:
Citation preview
Faculty of Computer Science, Institute for System Architecture, Operating Systems Group
EXERCISE 2: IPC
Inter-Process Communication
Benjamin Engel and Nils Asmussen
Dresden, 11/07/2017
Recap
• Inter-Process Communication– Send– Wait (open/closed)– Call: Send + closed Wait– Reply and Wait
• Message Payload– Plain data : copy– Capabilities (memory, kernel objects) : map
• Sync / Async– Sync: Rendezvous, direct copy sender→ receiver– Async: Queues, buffers, fire and forget
Exercise 2: IPC Slide 2 of 22
The Plan
• Echo server a.k.a. Log server– Send a string to a local echo server– Return the message to the caller
• Capability Delegation– Create your own echo server (Endpoint + Thread) and
send a capability for this server to another thread– Use your new echo server for logging
• Client-Server– Connection and Session management, server registers a
service, client looks it up
Exercise 2: IPC Slide 3 of 22
Setup
• Download the source archive fromhttp://os.inf.tu-dresden.de/˜nils/nova-nre.tar.gz
• tar xfz nova-nre.tar.gz
• cd cross && ./download.sh x86 64 (XOR ./build.sh)• Choose host platform (Ubuntu 15.04 x86 64)• cd ../nre (your working directory)
• Build via: ./b• Build and run via: ./b qemu boot/echo
• <DIR>/nre/apps/ipc: echo, delegate, client, server• <DIR>/nre/include: headers, e.g. UtcbFrame.h
Exercise 2: IPC Slide 4 of 22
NOVA Abstractions
• Thread / Execution Context (EC)– Unit of execution, thread or virtual machine
• Portal (PT)– Communication endpoint– Messages (data, capabilities) are sent to portals– Bound thread receives the messages
• Local Threads (services)– Wait/block in portals until get invoked/called– Return to the portal after request completion
• Global Threads– Run on their own
Exercise 2: IPC Slide 5 of 22
NRE Capability Hierarchy
ObjCap
Ec Pd Pt Sc
Thread
GlobalThreadLocalThread
VCpu
sel(): capsel_t
Pt(capsel_t)
create(cpu_t): Ref<LT> create(func, cpu_t): Ref<GT>
call(UF &): void
Pt(Ref<LT> <, func)
...
Exercise 2: IPC Slide 6 of 22
NRE UTCB Frames
Frame
Frame
UTCB1
push
pop
42
23
2
2 0
0
1 0
36
Cap(2)
Cap(14)
Sender
EC1
UTCB2
Receiver
EC2
Exercise 2: IPC Slide 7 of 22
NRE UTCB Frames
Frame
Frame
UTCB1
push
pop
42
23
2
2 0
0
1 0
36
Cap(2)
Cap(14)
Sender
EC1
UTCB2
Receiver
EC2
call()
Exercise 2: IPC Slide 8 of 22
NRE UTCB Frames
Frame
Frame
UTCB1
push
popFrame
42
23
2
2 2
0
1 0
36
Cap(2)
Cap(14)
Sender
EC1
UTCB2
Receiver
EC2
call()
42
23
Exercise 2: IPC Slide 9 of 22
NRE UTCB Usage• Data accessed via stream operators:
– read: UtcbFrame >> value;
– write: UtcbFrame << value;
• UtcbFrame::finish input()– Only required when reading AND writing– Needs to be done if reading is finished
• UtcbFrame constructor pushes a new frame on theUTCB, the destructor pops it again
Usage example
UtcbFrameRef uf; // UTCB frame
uf >> x; // read argument
uf.finish_input(); // end of input
uf << 2 * x; // write result back
Exercise 2: IPC Slide 10 of 22
Service ”Loop”
Fiasco.OC/L4Re Style
for(; receive(&utcb); reply(utcb)) {process message(utcb);
generate reply(&utcb);
}
• Receive: waits for incoming message
which is copied into receiver’s UTCB
• Handle message and generate reply
• Reply: copy reply into caller’s UTCB
and await next messageExercise 2: IPC Slide 11 of 22
Service ”Loop”
NOVA/NRE Style
PORTAL void portal function() {process message(utcb);
generate reply(&utcb);
}
• Receive: waits for incoming message
which is copied into receiver’s UTCB
• Handle message and generate reply
• Reply: copy reply into caller’s UTCB
and await next messageExercise 2: IPC Slide 12 of 22
1. Echo server (apps/echo)
// create a new thread
Reference<LocalThread> lt = LocalThread::create(
CPU::current().log_id());
// create a new portal for this thread
// Pt::Pt(const Reference<LocalThread>&, func_ptr);
Pt echo(lt, portal_echo);
{
UtcbFrame uf; // new UTCB frame
uf << 42; // fill in argument
echo.call(uf); // call server
int res;
uf >> res; // read result
}
Exercise 2: IPC Slide 13 of 22
1. Echo server (apps/echo)
• Implement service functionality• Read argument, send it back to the caller• Improvement: send two numbers a and b,
send back a+b / a-b / a*b / a/b . . .
Exercise 2: IPC Slide 14 of 22
Capability Space
Pd 1Thread A Portal
Thread BPd 2
kernel
user
Pd 1 Pd 2
01
3
01
Exercise 2: IPC Slide 15 of 22
Capability Delegation over IPCSender Pd Receiver Pd
KernelThread Portal Pd
Selectors
0 2 3
Pd Thread
1 2 3
UTCB1
Cap(3)
23
1
0
1
2
36
14
0 0
UTCB2
4 1
Selectors
Receive Window
Exercise 2: IPC Slide 16 of 22
Capability Delegation over IPCSender Pd Receiver Pd
KernelThread Portal Pd
Selectors
0 2 3
Pd Thread
1 2 3
UTCB1
Cap(3)
23
1
0
1
2
36
14
0 0
UTCB2
4 1
Selectors
Receive Window
call()
Exercise 2: IPC Slide 17 of 22
Capability Delegation over IPCSender Pd Receiver Pd
KernelThread Portal Pd
Selectors
0 2 3
Pd Thread
1 2 3
UTCB1
Cap(3)
23
1
0
1
2
36
14
1 1
UTCB2
Cap(4)
23
4 1
Selectors
Receive Window
call()
Exercise 2: IPC Slide 18 of 22
Capability Delegation over IPCSender Pd Receiver Pd
KernelThread Portal Pd
Selectors
0 2 3
Pd Thread
1 2 3
UTCB1
Cap(3)
23
1
0
1
2
36
14
1 1
UTCB2
Cap(4)
23
4 1
Selectors
Receive Window
call()
4
Exercise 2: IPC Slide 19 of 22
Capability Range Descriptor (Crd)
• Capabilities exchanged via:– send: UtcbFrame::delegate(cap);– receive: UtcbFrame::delegation window(Crd);
• Denote caps via Crd: type, offset and size• power-of-two sized, size-aligned, e.g:
– Offset 0, size = 1→ cap index 0– Offset 0, size = 2→ cap index 0-1– Offset 8, size = 4→ cap index 8-11– Offset 16, size = 32→ illegal, misaligned
Exercise 2: IPC Slide 20 of 22
2. Delegation (apps/delegate)// allocate/reserve num cap space indices
capsel_t CapSelSpace::get().allocate(num);
// open receive window for new caps
// see include/Desc.h for Crd details
Crd crd(start, order, Crd::OBJ_ALL);
UtcbFrame::delegation_window (crd);
// cap delegation: add cap to UTCB for sending
UtcbFrame::delegate(capsel_t sel);
// invoke portal, thereby receiving cap(s)
Pt::call(UtcbFrame&);
// create portal, bound to <sel>
Pt::Pt(capsel_t sel);
Exercise 2: IPC Slide 21 of 22
3. Client/Server// SERVER
PORTAL static void echo_func(void*) {
// ... service implementation
}
int main() {
Service *s = new Service("echo",
CPUSet(CPUSet::ALL), echo_func);
s->start();
}
// CLIENT
int main() {
PtClientSession sess("echo");
UtcbFrame uf;
sess.pt().call(uf);
}
Exercise 2: IPC Slide 22 of 22
Recommended