Lect8 424 002
Lect8 424 002
Lect8 424 002
Introduction to I/O,
Sockets, Networking
z
Recall: UNIX System Structure
Applications
User Mode
Standard Libs
Kernel Mode
Hardware
Word Processing
Compilers Web Browsers
Email
Databases Web Servers
Application / Service
Portable OS Library OS
User
System Call
System Interface
Portable OS Kernel
Software Platform support, Device Drivers
Request
Repl
(retrieved by web server)
Client Web Server
interrupt interrupt
2. copy arrivin 12. format outgoin 6. dis 7. disk data
packet (DMA) packet and DMA request (DMA)
Hardware
Network
interface Disk interface
Request Reply
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 5
y
interrupt interrupt
2. copy arrivin 12. format outgoin 6. dis 7. disk data
packet (DMA) packet and DMA request (DMA)
Hardware
Network
interface Disk interface
Request Reply
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 9
y
interrupt interrupt
2. copy arrivin 12. format outgoin 6. dis 7. disk data
packet (DMA) packet and DMA request (DMA)
Hardware
Network
interface Disk interface
Request Reply
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 10
y
Syscall registers
#include <stdio.h
FILE *fopen( const char *filename, const char *mode )
int fclose( FILE *fp );
sh
flu
r rb Open existing file for reading
to
w wb Open for writing; created if does not exist
t
ge
for
a ab Open for appending; created if does not exist
n’t
r+ rb+ Open existing file for reading & writing.
Do
w+ wb+ Open for reading & writing; truncated to zero if exists, create otherwise
a+ ab+ Open for reading & writing. Created if does not exist. Read from beginning, write
as append
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 13
>
// block oriente
size_t fread(void *ptr, size_t size_of_elements,
size_t number_of_elements, FILE *a_file)
// formatte
int fprintf(FILE *restrict stream, const char *restrict
format, ...)
int fscanf(FILE *restrict stream, const char *restrict
format, ...);
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 16
d
>
;
;
int main(void)
FILE* input = fopen(“input.txt”, “r”)
FILE* output = fopen(“output.txt”, “w”)
int c
c = fgetc(input)
while (c != EOF)
fputc(output, c)
c = fgetc(input)
fclose(input)
fclose(output)
}
>
// block oriente
size_t fread(void *ptr, size_t size_of_elements,
size_t number_of_elements, FILE *a_file)
// formatte
int fprintf(FILE *restrict stream, const char *restrict
format, ...)
int fscanf(FILE *restrict stream, const char *restrict
format, ...);
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 18
d
>
;
;
fclose(input)
fclose(output)
}
>
whence
offset (SEEK_CUR)
Application / Service
High Level I/O streams
#include <fcntl.h
#include <unistd.h
#include <sys/types.h
http://www.gnu.org/software/libc/manual/html_node/Opening-and-Closing-Files.html
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 23
:
>
>
>
#include <unistd.h
• When write returns, data is on its way to disk and can be read,
but it may not actually be permanent!
#include <fcntl.h
#include <unistd.h
#include <sys/types.h
int main()
char buf[1000]
int fd = open("lowio.c", O_RDONLY, S_IRUSR | S_IWUSR)
ssize_t rd = read(fd, buf, sizeof(buf))
int err = close(fd)
ssize_t wr = write(STDOUT_FILENO, buf, rd)
}
>
>
>
Another: lowio-std.c
#include <stdlib.h
#include <stdio.h
#include <string.h
#include <unistd.h
#include <sys/types.h
char buf[BUFSIZE]
ssize_t writelen = write(STDOUT_FILENO, "I am a process.\n", 16)
exit(0)
}
>
>
>
>
>
int main(void)
int input_fd = open(“input.txt”, O_RDONLY)
int output_fd = open(“output.txt”, O_WRONLY)
char buffer[BUFFER_SIZE]
ssize_t length
length = read(input_fd, buffer, BUFFER_SIZE)
while (length > 0)
write(output_fd, buffer, length)
length = read(input_fd, buffer, BUFFER_SIZE)
close(input_fd)
close(output_fd)
}
>
>
• Low level lib parameters are set up in registers and syscall instruction is
issue
– A type of synchronous exception that enters well-defined entry points
into kernel
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 33
d
Application / Service
File descriptor numbe
- an int High Level I/O streams
Low Level I/O handles
Syscall registers
File System descriptors
File Descriptor
• a struct with all the info I/O Driver Commands and Data Transfers
about the files Disks, Flash, Controllers, DMA
• Pointer:
struct file *file
s
inc_syscr(current)
return ret
}
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 36
{
ssize_t ret
if (!(file->f_mode & FMODE_READ)) return -EBADF
if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read)
return -EINVAL
if (unlikely(!access_ok(VERIFY_WRITE, buf, count))) Make sure-EFAULT
return we are
ret = rw_verify_area(READ, file, pos, count)
allowed to read this
if (ret >= 0)
count = ret file
if (file->f_op->read
ret = file->f_op->read(file, buf, count, pos)
els
ret = do_sync_read(file, buf, count, pos)
if (ret > 0)
fsnotify_access(file->f_path.dentry)
add_rchar(current, ret)
inc_syscr(current)
return ret
}
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 37
{
ssize_t ret
if (!(file->f_mode & FMODE_READ)) return -EBADF
if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read)
return -EINVAL
if (unlikely(!access_ok(VERIFY_WRITE, buf, count))) return -EFAULT
ret = rw_verify_area(READ, file, pos, count)
if (ret >= 0) Check if file has
count = ret
read methods
if (file->f_op->read
ret = file->f_op->read(file, buf, count, pos)
els
ret = do_sync_read(file, buf, count, pos)
if (ret > 0)
fsnotify_access(file->f_path.dentry)
add_rchar(current, ret)
inc_syscr(current)
return ret
}
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 38
{
ssize_t ret
if (!(file->f_mode & FMODE_READ)) return -EBADF
if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read)
return -EINVAL
if (unlikely(!access_ok(VERIFY_WRITE, buf, count))) return -EFAULT
ret = rw_verify_area(READ, file, pos, count)
if (ret >= 0)
count = ret
if (file->f_op->read •Check whether we can write to buf (e.g.,
buf ispos)
ret = file->f_op->read(file, buf, count, in the user space range)
els •unlikely(): hint to branch prediction this
ret = do_sync_read(file, buf, count, condition
pos) is unlikel
if (ret > 0)
fsnotify_access(file->f_path.dentry)
add_rchar(current, ret)
inc_syscr(current)
return ret
}
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 39
{
ssize_t ret
if (!(file->f_mode & FMODE_READ)) return -EBADF
if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read)
return -EINVAL
if (unlikely(!access_ok(VERIFY_WRITE, buf, count))) return -EFAULT
ret = rw_verify_area(READ, file, pos, count)
if (ret >= 0)
count = ret
if (file->f_op->read
Check whether we read from a
ret = file->f_op->read(file, buf, count, pos)
els valid range in the file.
ret = do_sync_read(file, buf, count, pos)
if (ret > 0)
fsnotify_access(file->f_path.dentry)
add_rchar(current, ret)
inc_syscr(current)
return ret
}
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 40
{
ssize_t ret
if (!(file->f_mode & FMODE_READ)) return -EBADF
if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read)
return -EINVAL
if (unlikely(!access_ok(VERIFY_WRITE, buf, count))) return -EFAULT
ret = rw_verify_area(READ, file, pos, count)
if (ret >= 0)
count = ret
if (file->f_op->read
ret = file->f_op->read(file, buf, count, pos)
els
ret = do_sync_read(file, buf, count, pos)
if (ret > 0)
fsnotify_access(file->f_path.dentry)
add_rchar(current, ret) If driver provide a read function
(f_op->read) use it; otherwise use
inc_syscr(current) do_sync_read()
return ret
}
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 41
{
ssize_t ret
if (!(file->f_mode & FMODE_READ)) return -EBADF
if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read)
return -EINVAL
if (unlikely(!access_ok(VERIFY_WRITE, buf, count))) return -EFAULT
ret = rw_verify_area(READ, file, pos, count)
if (ret >= 0)
count = ret
if (file->f_op->read Notify the parent of this file that the file was read (see
http://www.fieldses.org/~bfields/kernel/vfs.txt
ret = file->f_op->read(file, buf, count, pos)
els
ret = do_sync_read(file, buf, count, pos)
if (ret > 0)
fsnotify_access(file->f_path.dentry)
add_rchar(current, ret)
inc_syscr(current)
return ret
}
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 42
{
)
;
ssize_t ret
if (!(file->f_mode & FMODE_READ)) return -EBADF
if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read)
return -EINVAL
if (unlikely(!access_ok(VERIFY_WRITE, buf, count))) return -EFAULT
ret = rw_verify_area(READ, file, pos, count)
if (ret >= 0)
count = ret
if (file->f_op->read
Update the number of bytes
ret = file->f_op->read(file, buf, count, pos)
els read by “current” task (for
ret = do_sync_read(file, buf, count, pos) scheduling purposes
if (ret > 0)
fsnotify_access(file->f_path.dentry)
add_rchar(current, ret)
inc_syscr(current)
return ret
}
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 43
{
)
{
ssize_t ret
if (!(file->f_mode & FMODE_READ)) return -EBADF
if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read)
return -EINVAL
if (unlikely(!access_ok(VERIFY_WRITE, buf, count))) return -EFAULT
ret = rw_verify_area(READ, file, pos, count)
if (ret >= 0)
count = ret
if (file->f_op->read
ret = file->f_op->read(file, buf, count, pos)
els
Update the number of read
ret = do_sync_read(file, buf, count, pos)
if (ret > 0) syscalls by “current” task (for
fsnotify_access(file->f_path.dentry) scheduling purposes
add_rchar(current, ret)
inc_syscr(current)
return ret
}
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 44
{
)
{
Device Drivers
• Device Driver: Device-specific code in the kernel that interacts
directly with the device hardwar
– Supports a standard, internal interface
– Same kernel I/O system can interact easily with different device drivers
– Special device-specific configuration supported with the ioctl() system call
• Device Drivers typically divided into two pieces
– Top half: accessed in call path from system calls
» implements a set of standard, cross-device calls like open(), close(),
read(), write(), ioctl(), strategy()
» This is the kernel’s interface to the device drive
» Top half will start I/O to device, may put thread to sleep until finishe
– Bottom half: run as interrupt routine
» Gets input or transfers next block of outpu
» May wake sleeping threads if I/O now complete
Kernel I/
Subsystem
Device Drive
Top Half
Device Drive
Bottom Half
Devic
Hardware
n = read(rfd,rbuf,rmax);
n = read(rfd,rbuf,rmax);
requests
n = read(rfd,rbuf,rmax);
responses
n = read(resfd,resbuf,resmax);
requests
n = read(rfd,rbuf,rmax);
n = read(resfd,resbuf,resmax);
Client 1
Client 2 Server
***
Client n
Client-Server Communication
Sockets
• Socket: an abstraction of a network I/O queu
– Mechanism for inter-process communication
– Embodies one side of a communication channe
» Same interface regardless of location of other en
» Could be local machine (called “UNIX socket”) or remote machine (called
“network socket”
– First introduced in 4.2 BSD UNIX: big innovation at tim
» Now most operating systems provide some notion of socke
• Data transfer like file
– Read / Write against a descripto
• Over ANY kind of networ
– Local to a machin
– Over the internet (TCP/IP, UDP/IP
– OSI, Appletalk, SNA, IPX, SIP, NS, …
gets(fd,sndbuf, …);
requests
write(fd, buf,len);
n = read(fd,buf,);
wait print
write(fd, buf,);
responses
n = read(fd,rcvbuf, );
print
;
;
• When ready
– File read gets whatever is there at the time. Assumes writing
already took place.
– Like pipes!
Client Server
Client Server
• Server Socket: Listens for new connection
– Produces new sockets for each unique connection
– 3-way handshake to establish new connection
• Things to remember
– Connection involves 5 values:
[ Client Addr, Client Port, Server Addr, Server Port, Protocol ]
– Often, Client Port “randomly” assigned
» Done by OS during client socket setup
– Server Port often “well known”
» 80 (web), 443 (secure web), 25 (sendmail), et
» Well-known ports from 0—1023
2/18/2020 Kubiatowicz CS162 ©UCB Fall 2020 61
c
Accept syscall()
Connection Socket Connection Socket
write request read request
read response write response
Client Protocol
// Create a socke
struct addrinfo *server = lookup_host(host_name, port_name)
int sock_fd = socket(server->ai_family, server->ai_socktype
server->ai_protocol)
/* Clean up on termination *
close(sock_fd);
return server
}
while (1)
// Accept a new client connection, obtaining a new socke
int conn_socket = accept(server_socket, NULL, NULL)
serve_client(conn_socket)
close(conn_socket)
close(server_socket);
• Simple for
• Internet Protocol, TC
• Accepting any connections on the specified port
Accept syscall()
close(server_socket);
{
{
;
{
;
;
;
;
;
;
Concurrent Server
• Listen will queue request
• Buffering present elsewher
• But server waits for each connection to terminate before
initiating the next
Accept syscall()
close(server_socket);
{
{
{
;
;
;
;
;
;
;
;
Conclusion (I)
• System Call Interface is “narrow waist” between user programs and
kerne
• Low-level I/O:
– File descriptors are integer
– Low-level I/O supported directly at system call leve
Conclusion (II)