Slide 1

Slide 1 text

Ruby Systems Programming Andy delcambre Monday, March 11, 13

Slide 2

Slide 2 text

@adelcambre sounds like welcome Andy Delcambre Monday, March 11, 13

Slide 3

Slide 3 text

Monday, March 11, 13

Slide 4

Slide 4 text

gist Monday, March 11, 13

Slide 5

Slide 5 text

Monday, March 11, 13

Slide 6

Slide 6 text

diploma goes here Monday, March 11, 13

Slide 7

Slide 7 text

Delcambre Software Monday, March 11, 13

Slide 8

Slide 8 text

CS 333 Operating systems CS 494 Networking Monday, March 11, 13

Slide 9

Slide 9 text

Monday, March 11, 13

Slide 10

Slide 10 text

Ruby Systems Programming Monday, March 11, 13

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

User Mode Kernel Mode Monday, March 11, 13

Slide 13

Slide 13 text

User Mode Monday, March 11, 13

Slide 14

Slide 14 text

User Mode Math Monday, March 11, 13

Slide 15

Slide 15 text

User Mode Math Access Memory* Monday, March 11, 13

Slide 16

Slide 16 text

Kernel Mode Monday, March 11, 13

Slide 17

Slide 17 text

Kernel Mode Anything Monday, March 11, 13

Slide 18

Slide 18 text

Kernel Mode Anything Everything Monday, March 11, 13

Slide 19

Slide 19 text

User Mode Kernel Mode Monday, March 11, 13

Slide 20

Slide 20 text

User Mode Kernel Mode Your Program System Calls Monday, March 11, 13

Slide 21

Slide 21 text

Obligatory Jessica Monday, March 11, 13

Slide 22

Slide 22 text

$ strace -p Monday, March 11, 13

Slide 23

Slide 23 text

Monday, March 11, 13

Slide 24

Slide 24 text

120,602 Calls One Request Monday, March 11, 13

Slide 25

Slide 25 text

linux$ wc -l syscall_table.S 326 Monday, March 11, 13

Slide 26

Slide 26 text

mov!eax, 5 mov!ebx, path mov!ecx, flags int!80h open(path, flags) Monday, March 11, 13

Slide 27

Slide 27 text

linux$ cat syscall_table.S | grep -c sys_ni_syscal 65 Monday, March 11, 13

Slide 28

Slide 28 text

linux$ cat syscall_table.S | grep -c sys_ni_syscal 65 “Not Implemented” Monday, March 11, 13

Slide 29

Slide 29 text

Monday, March 11, 13

Slide 30

Slide 30 text

1980 1970 1960 1990 Multics Unix (Unics) BSD BSD 4.2 TCP/IP Monday, March 11, 13

Slide 31

Slide 31 text

BSD Sockets Monday, March 11, 13

Slide 32

Slide 32 text

•socket() •bind() •listen() •accept() •send() and recv() •close() Monday, March 11, 13

Slide 33

Slide 33 text

TCP Client Server SYN SYN/ACK Data ACK Data/ACK FIN ACK FIN ACK ACK Monday, March 11, 13

Slide 34

Slide 34 text

TCP Client Server SYN SYN/ACK Data ACK Data/ACK FIN ACK FIN ACK ACK Monday, March 11, 13

Slide 35

Slide 35 text

TCP Client Server SYN SYN/ACK Data ACK Data/ACK FIN ACK FIN ACK ACK Monday, March 11, 13

Slide 36

Slide 36 text

TCP Client Server SYN SYN/ACK Data ACK Data/ACK FIN ACK FIN ACK ACK Monday, March 11, 13

Slide 37

Slide 37 text

$ lsof -p 34866 -a -i COMMAND PID TYPE NODE NAME ruby 34866 IPv4 TCP 127.0.0.1:80 (LISTEN) ruby 34866 IPv4 TCP 127.0.0.1:80->127.0.0.1:61898 (ESTABLISHED) Monday, March 11, 13

Slide 38

Slide 38 text

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

Slide 39

Slide 39 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 Monday, March 11, 13

Slide 40

Slide 40 text

There Will be Code Monday, March 11, 13

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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end Monday, March 11, 13

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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end Require the socket lib Monday, March 11, 13

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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end Some constants for later Monday, March 11, 13

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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end socket = Socket.new(:INET, :STREAM) Monday, March 11, 13

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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end sockaddr = Socket.sockaddr_in(11080, '127.0.0.1') socket.bind(sockaddr) Monday, March 11, 13

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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end socket.listen(5) Monday, March 11, 13

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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end while client_socket = socket.accept[0] Monday, March 11, 13

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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end path = client_socket.recv(1024).split[1] Monday, March 11, 13

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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end path = client_socket.recv(1024).split[1] GET /index.html HTTP/1.1 Monday, March 11, 13

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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end filename = File.expand_path("../#{path}", __FILE__) Monday, March 11, 13

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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end if File.file?(filename) Monday, March 11, 13

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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) Monday, March 11, 13

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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) OK = "HTTP/1.1 200 OK\n" Monday, March 11, 13

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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end client_socket.send(NOT_FOUND, 0) Monday, March 11, 13

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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end client_socket.send(NOT_FOUND, 0) NOT_FOUND = "HTTP/1.1 404 Not Found\nContent-Length: 9\n\nNot Found" Monday, March 11, 13

Slide 56

Slide 56 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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end client_socket.close Monday, March 11, 13

Slide 57

Slide 57 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.recv(1024).split[1] filename = File.expand_path("../#{path}", __FILE__) if File.file?(filename) contents = File.read(filename) client_socket.send(OK, 0) client_socket.send("Content-Length: #{contents.size}\n\n", 0) client_socket.send("#{contents}", 0) else client_socket.send(NOT_FOUND, 0) end client_socket.close end Monday, March 11, 13

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 Monday, March 11, 13

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 sock = Socket.new(AF_INET6, SOCK_STREAM, 0) Monday, March 11, 13

Slide 60

Slide 60 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)) Monday, March 11, 13

Slide 61

Slide 61 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) Monday, March 11, 13

Slide 62

Slide 62 text

Thanks! @adelcambre Monday, March 11, 13