Slide 1

Slide 1 text

Systems Programming

Slide 2

Slide 2 text

operate and control the computer hardware and to provide a platform for running application software http://en.wikipedia.org/wiki/System_software “

Slide 3

Slide 3 text

application software “

Slide 4

Slide 4 text

web software “

Slide 5

Slide 5 text

Building Blocks The Kernel System Calls Sockets File Descriptors HTTP

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

The Kernel

Slide 8

Slide 8 text

Your Code The Kernel Hardware

Slide 9

Slide 9 text

Your Code

Slide 10

Slide 10 text

Your Code User Mode

Slide 11

Slide 11 text

Your Code Math User Mode

Slide 12

Slide 12 text

Your Code Math Access Memory User Mode

Slide 13

Slide 13 text

The Kernel

Slide 14

Slide 14 text

The Kernel Anything

Slide 15

Slide 15 text

The Kernel Anything Everything

Slide 16

Slide 16 text

System Calls

Slide 17

Slide 17 text

User Mode Kernel Mode

Slide 18

Slide 18 text

User Mode Kernel Mode Your Program System Calls

Slide 19

Slide 19 text

$ strace -p

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

120,602 Calls One Request

Slide 22

Slide 22 text

linux$ wc -l syscall_table.S 326

Slide 23

Slide 23 text

mov! eax, 5 mov! ebx, path mov! ecx, flags int! 80h open(path, flags)

Slide 24

Slide 24 text

linux$ cat syscall_table.S | grep -c sys_ni_syscal 65 Not Implemented

Slide 25

Slide 25 text

File Descriptors

Slide 26

Slide 26 text

Everything is a File

Slide 27

Slide 27 text

Things that are Files (Non Exhaustive)

Slide 28

Slide 28 text

Things that are Files (Non Exhaustive) Files

Slide 29

Slide 29 text

Things that are Files (Non Exhaustive) Links DVDs Hard Drives USB Keys Sockets* Files Directories Sound Cards Graphics Cards Printers Pipes Terminals UNIX Sockets Shared Memory

Slide 30

Slide 30 text

read() write() close() lseek()* File API

Slide 31

Slide 31 text

0 -> /dev/null 1 -> unicorn.log 2 -> unicorn.log 3 -> pipe:[3753224456] 4 -> pipe:[3753224456] 5 -> socket:[19730] 6 -> pipe:[3753224457] 7 -> socket:[19731] 8 -> socket:[19732] 9 -> pipe:[3753224457] 10 -> production.log 11 -> socket:[3766066290] 12 -> socket:[3753228795] 13 -> socket:[3753229266] 14 -> socket:[3753229276] 15 -> socket:[3753229285] 16 -> socket:[3753229307] 17 -> socket:[3753235718] 18 -> socket:[3753235910] 19 -> socket:[3753242775] 20 -> socket:[3753242776] 21 -> socket:[3753242778] 22 -> socket:[3753239097] 23 -> socket:[3753242942] 24 -> socket:[3753242944] 25 -> socket:[3753239202] 26 -> socket:[3753239203] 27 -> socket:[3753239204] 28 -> socket:[3753242981] 29 -> socket:[3753242982] 30 -> socket:[3753243929] 31 -> socket:[3753240046] 32 -> socket:[3753245881] 33 -> socket:[3753248970] 34 -> socket:[3753253476] 35 -> pygments-ruby.log 36 -> /dev/null 37 -> pipe:[3753260503] 38 -> pipe:[3753260504] 39 -> socket:[3753344667] 40 -> pipe:[3753260505] 41 -> socket:[3765810413] 42 -> socket:[3765810440] 43 -> socket:[3765848228] $ ls -l /proc/32660/fd

Slide 32

Slide 32 text

BSD Sockets

Slide 33

Slide 33 text

1980 1970 1960 1990 Multics Unix (Unics) BSD BSD 4.2 TCP/IP

Slide 34

Slide 34 text

socket() bind() listen() accept() read() and write() close()

Slide 35

Slide 35 text

HTTP

Slide 36

Slide 36 text

HTTP Request GET /index.html HTTP/1.1 User-Agent: curl/7.24.0 Host: www.google.com Accept: */*

Slide 37

Slide 37 text

HTTP Response HTTP/1.1 200 OK Date: Tue, 05 Mar 2013 23:03:52 GMT Cache-Control: private, max-age=0 Content-Type: text/html Server: gws Transfer-Encoding: chunked

Slide 38

Slide 38 text

There Will be Code

Slide 39

Slide 39 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end

Slide 40

Slide 40 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end Require the socket lib

Slide 41

Slide 41 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end Some constants for later

Slide 42

Slide 42 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end socket = Socket.new(:INET, :STREAM)

Slide 43

Slide 43 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr)

Slide 44

Slide 44 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end socket.listen(5)

Slide 45

Slide 45 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end while client_socket = socket.accept[0]

Slide 46

Slide 46 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end path = client_socket.readline.split[1]

Slide 47

Slide 47 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end path = client_socket.readline.split[1] GET /index.html HTTP/1.1

Slide 48

Slide 48 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end filename = File.expand_path("../#{path}", __FILE__)

Slide 49

Slide 49 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end if File.file?(filename)

Slide 50

Slide 50 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}")

Slide 51

Slide 51 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") OK = "HTTP/1.1 200 OK\n"

Slide 52

Slide 52 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end client_socket.write(NOT_FOUND)

Slide 53

Slide 53 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end client_socket.write(NOT_FOUND) NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found"

Slide 54

Slide 54 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end client_socket.close

Slide 55

Slide 55 text

require 'socket' NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" OK = "HTTP/1.1 200 OK\n" socket = Socket.new(:INET, :STREAM) sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) socket.listen(5) while client_socket = socket.accept[0] path = client_socket.readline.split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.write(OK) client_socket.write("Content-Length: #{contents.size}\n\n") client_socket.write("#{contents}") else client_socket.write(NOT_FOUND) end client_socket.close end

Slide 56

Slide 56 text

def new_ipv6_server(addr, port, opt) opt.key?(:ipv6only) or return Kgio::TCPServer.new(addr, port) defined?(IPV6_V6ONLY) or abort "Socket::IPV6_V6ONLY not defined, upgrade Ruby and/or your OS" sock = Socket.new(AF_INET6, SOCK_STREAM, 0) sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, opt[:ipv6only] ? 1 : 0) sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) sock.bind(Socket.pack_sockaddr_in(port, addr)) IO_PURGATORY << sock Kgio::TCPServer.for_fd(sock.fileno) end ret = IO.select(l, nil, SELF_PIPE, @timeout) and ready = ret[0] Unicorn

Slide 57

Slide 57 text

def new_ipv6_server(addr, port, opt) opt.key?(:ipv6only) or return Kgio::TCPServer.new(addr, port) defined?(IPV6_V6ONLY) or abort "Socket::IPV6_V6ONLY not defined, upgrade Ruby and/or your OS" sock = Socket.new(AF_INET6, SOCK_STREAM, 0) sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, opt[:ipv6only] ? 1 : 0) sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) sock.bind(Socket.pack_sockaddr_in(port, addr)) IO_PURGATORY << sock Kgio::TCPServer.for_fd(sock.fileno) end ret = IO.select(l, nil, SELF_PIPE, @timeout) and ready = ret[0] Unicorn sock = Socket.new(AF_INET6, SOCK_STREAM, 0)

Slide 58

Slide 58 text

def new_ipv6_server(addr, port, opt) opt.key?(:ipv6only) or return Kgio::TCPServer.new(addr, port) defined?(IPV6_V6ONLY) or abort "Socket::IPV6_V6ONLY not defined, upgrade Ruby and/or your OS" sock = Socket.new(AF_INET6, SOCK_STREAM, 0) sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, opt[:ipv6only] ? 1 : 0) sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) sock.bind(Socket.pack_sockaddr_in(port, addr)) IO_PURGATORY << sock Kgio::TCPServer.for_fd(sock.fileno) end ret = IO.select(l, nil, SELF_PIPE, @timeout) and ready = ret[0] Unicorn sock.bind( Socket.pack_sockaddr_in(port, addr))

Slide 59

Slide 59 text

def new_ipv6_server(addr, port, opt) opt.key?(:ipv6only) or return Kgio::TCPServer.new(addr, port) defined?(IPV6_V6ONLY) or abort "Socket::IPV6_V6ONLY not defined, upgrade Ruby and/or your OS" sock = Socket.new(AF_INET6, SOCK_STREAM, 0) sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, opt[:ipv6only] ? 1 : 0) sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) sock.bind(Socket.pack_sockaddr_in(port, addr)) IO_PURGATORY << sock Kgio::TCPServer.for_fd(sock.fileno) end ret = IO.select(l, nil, SELF_PIPE, @timeout) and ready = ret[0] Unicorn IO.select(l, nil, SELF_PIPE, @timeout)

Slide 60

Slide 60 text

The Kernel System Calls Sockets File Descriptors HTTP

Slide 61

Slide 61 text

Further Reading Linux System Programming Robert Love

Slide 62

Slide 62 text

Further Reading Unix Network Programming Richard Stevens

Slide 63

Slide 63 text

Further Reading Advanced Programming in the UNIX Environment Richard Stevens

Slide 64

Slide 64 text

Andy Delcambre adelcambre @

Slide 65

Slide 65 text

No content

Slide 66

Slide 66 text

Thanks! adelcambre @