Systems Programming.

Slides:



Advertisements
Similar presentations
Today’s topic: –File operations –I/O redirection –Inter-process communication through pipes.
Advertisements

Process Control Hua LiSystems ProgrammingCS2690Process Control Page 1 of 41.
CS 311 – Lecture 14 Outline Process management system calls Introduction System calls  fork()  getpid()  getppid()  wait()  exit() Orphan process.
CS 311 – Lecture 09 Outline Introduction to Systems programming – System calls – Categories of system calls Error Management System calls File Handling.
Exec function Exec function: - replaces the current process (its code, data, stack & heap segments) with a new program - the new program starts executing.
Files. System Calls for File System Accessing files –Open, read, write, lseek, close Creating files –Create, mknod.
1 Advanced programming in UNIX 1 File I/O Hua LiSystems ProgrammingCS2690File I/O.
Process Control in Unix Operating Systems Hebrew University Spring 2004.
CSE 451 Section 4 Project 2 Design Considerations.
Fork and Exec Unix Model Tutorial 3. Process Management Model The Unix process management model is split into two distinct operations : 1. The creation.
CS 311 – Lecture 12 Outline File management system calls Stat() Directory Information  Opendir()  Readdir()  Closedir() Truncate() and remove() Lecture.
1 Unix File System API Operating System Hebrew University Spring 2007.
Shell (Part 1). Process r A process is an instance of an application running r If there are two instances of an application running then there are two.
Adv. UNIX: lowIO/161 Advanced UNIX v Objectives –look at low-level operations for handling files Special Topics in Comp. Eng. 2 Semester.
Fundamentals CIS 552. Fundamentals Low-level I/O (read/write using system calls)  Opening/Creating files  Reading & Writing files  Moving around in.
1 UNIX System Programming v Objectives –look at how to program with directories –briefly describe the UNIX file system Directories and File System.
CS252: Systems Programming Ninghui Li Based on Slides by Prof. Gustavo Rodriguez-Rivera Topic 8: Opening Files and Starting Processes.
Silberschatz, Galvin and Gagne ©2013 Operating System Concepts Essentials – 9 th Edition Chapter 3: Processes.
Process Control Process identifiers Process creation fork and vfork wait and waitpid Race conditions exec functions system function.
System calls for Process management
Files and Directories File types stat functions for file information
Process Management CS3320 Spring Process A process is an instance of a running program. –Not the same as “program” or “processor” Process provides.
Operating Systems Process Creation
What is a Process? u A process is an executable “cradle” in which a program may run u This “cradle” provides an environment in which the program can run,
Today’s topic Access and manipulate meta data for files –File type, ownership, access permissions, access time, etc How to determine if a file is not there?
CSCI 330 UNIX and Network Programming Unit XII: Process & Pipe Part 1.
CSCI 330 UNIX and Network Programming Unit VII: I/O Management I.
Laface 2007 File system 2.1 Operating System Design Filesystem system calls buffer allocation algorithms getblk brelse bread breada bwrite iget iput bmap.
CSCI 330 UNIX and Network Programming
Process Management Azzam Mourad COEN 346.
CSE333 SECTION 3. Important Dates Jan 27 th – Homework 1 Due Feb 6 th – Midterm.
January 7, 2003Serguei Mokhov, 1 File I/O System Calls Reference COMP 229, 444, 5201 Revision 1.2 Date: July 21, 2004.
Copyright ©: Nahrstedt, Angrave, Abdelzaher1 Tarek Abdelzaher Vikram Adve CS241 Systems Programming System Calls and I/O.
CS 241 Section Week #8 (10/29/09). Outline MP5 Overview Files & I/O UNIX File Systems inodes Directories Links.
Library Functions The UNIX system provides a large number of C functions as libraries. Some of these implement frequently used operations, while others.
File I/O open close lseek read and write – unbuffered I/O dup and dup2.
CSCI 330 UNIX and Network Programming Unit VIII: I/O Management II.
OS interface: file and I/O system calls File operations in C/C++? –fopen(), fread(), fwrite(), fclose(), fseek() in C f.open(…), f.close(…) in C++ I/O.
File Subsystem in Linux by Dr P.Padmanabham Professor (CSE)&Director Bharat Institute of Engineering &Technology Hyderabad Mobile
CSC 271 – Software I: Utilities and Internals An Introduction to File I/O in Linux Credited to Dr. Robert Siegfried and Beginning Linux Programming by.
Process Related System Calls By Neha Hulkoti & Kavya Bhat.
Using System Calls (Unix) Have to tell compiler (if C/C++) where to find the headers, etc. – i.e., the “include” files May have to tell compiler where.
Lecture 3: System Calls & API Standards
Today topics: File System Implementation
Lecture 31: Introduction to File System
LINUX System : Lecture 8 Programming with Processes
Week 12 - Wednesday CS222.
Using Processes.
UNIX System Overview.
UNIX PROCESSES.
Tarek Abdelzaher Vikram Adve Marco Caccamo
Directory Directory is a file containing list of entries,where each entry represents inode number and name of the file stored in that directory.
Lecture 5: Process Creation
Fork and Exec Unix Model
Operating System Hebrew University Spring 2004
Unix Directories unix etc home pro dev motd snt unix ... slide1 slide2
LINUX System Programming with Processes (additional)
CSE 333 – Section 3 POSIX I/O Functions.
File Structure Related system calls
Tutorial 3 Tutorial 3.
File I/O (1) Prof. Ikjun Yeom TA – Mugyo
Process Programming Interface
CSE 333 – Section 3 POSIX I/O Functions.
Advanced UNIX progamming
CSE 333 – Section 3 POSIX I/O Functions.
FILE I/O File Descriptors I/O Efficiency File Sharing
File I/O & UNIX System Interface
Internal Representation of Files
Week 12 - Wednesday CS222.
Unix Directories unix etc home pro dev motd snt unix ... slide1 slide2
Presentation transcript:

Systems Programming

Systems Programming System calls is a programmer’s functional interface to the UNIX kernel. File management Process management Error handling

Error Handling: errno Most system calls are capable of failing. It if happens, system call returns a value of -1. -1 gives no clue why the error occurred. Each process has a global variable errno that holds the numeric code of the last system-call error. (Initially, it 0). “/usr/include/sys/errno.h” #define EPERM 1 /*Operation not permitted*/ #define ENOENT 2 /*No such file or directory*/ #define EIO 5 /* I/O error */ #define EMFILE 24 /* Too many open files */ #include <errno.h>

Error Handling: perror() void perror(char *str) Displays str : description of the last system call error. No error: “Error 0”. errno should be manually reset to 0 after system call failure!

Error Handling: perror() errno=2 main: No such file or directory main: Error 0

Unix File System Unix files are organized by hierarchy of labels commonly known as directory structure. Regular files: sequence of bytes that generally corresponds to code or data. Directory files: stored in a special format and form the backbone of the file system (directory- specific system calls). Special files correspond to peripherals, such as printers, disks, pipes and sockets. File 0 byte A UNIX file is a linear sequence of bytes.

File Descriptor File descriptor is a non-negative integer returned by open() or creat(), it is used in subsequent I/0 system calls on the file. File descriptors are numbered subsequently. By convention, 0 – stdin, 1 – stdout, 2 – strerr. Each descriptor has its private set of properties: a file pointer (offset within file; is changed by read/write/lseek) flag indicating if the file descriptor File 0 byte should automatically be closed if the process execs flag indicating if all of the output to the file should be appended to the end of file.

File Management System Calls Manipulates regular, directory and special files.

Opening a File: open() int open(char* fileName, int mode[, int perm]) fileName: absolute or relative pathname mode(|): O_RDONLY, O_WRONLY, O_RDWR O_APPEND: file pointer is at the end of the file before each write() O_CREAT: if file doesn’t exist, create it with process’s effective UID as owner ID. O_EXCL: if O_CREAT and file exists, then open() fails. O_NONBLOCK: pipes O_TRUNC: if file exists, it is truncated to length 0. perm: permission (octal number) of created file . Returns lowest unopened nonnegative file descriptor, or -1 if fails.

Creating a File #include<fcntl.h> #include<stdio.h> #include<stdlib.h> void main(){ int fd = open (“reverse.c”, O_CREAT | O_RDWR, 0600); if (fd == -1) { perror ("reverse: "); exit (1); } … }

Opening an Existing File #include<fcntl.h> #include<stdio.h> #include<stdlib.h> void main(int argc,char *argv[]){ if (argc>1) { int fd = open (argv[1], O_RDONLY); if (fd == -1) { perror ("reverse: "); exit (1); } … }}

Creating a File: creat() int creat(char* fileName, mode_t perm) open(fileName, O_CREAT|O_WRONLY|O_TRUNC,perm) <sys/stat.h> S_IRUSR: owner read permit S_IWUSR: owner write permit S_IXUSR: owner execute permit S_IRGRP: group read permit S_IWGRP: group write permit S_IROTH: others read permit S_IWOTH: owners write permit S_IXOTH: others execute permit open(“myfile”, O_CREAT, S_IRUSR | S_IXOTH)  

Reading from a Regular File: read() size_t read(int fd, void* buf, size_t count) Copies up to count bytes from the file referenced by fd into the buffer buf. Updates current file position. If successful, returns number of bytes that it read; otherwise, -1. If it was attempted after the last byte has already been read, returns 0 (EOF). Low-level input: no formatting capabilities of scanf. Faster than scanf.

Assume, fd points to some file. int charsRead; char buffer [4096]; while (1) { charsRead = read (fd, buffer, 4096); if (charsRead == 0) break; /* EOF */ if (charsRead == -1) { perror ("reverse: "); exit (1); } …

Writing to a Regular File: write() size_t write(int fd, void* buf, size_t count) Copies up to count bytes from the buffer buf to the file referenced by fd. If O_APPEND was set for fd, file position is set to the end of the file before each write. Updates current file position. If successful, returns number of bytes that were written; otherwise, -1. If returned number is less than count, then the disk probably filled up. Low-level output: no formatting capabilities.

Assume, fd and out are two file descriptors. int charsRead, charsWritten; char buffer [4096]; while (1) { charsRead = read (fd, buffer, 4096); if (charsRead == 0) break; /* EOF */ if (charsRead == -1) { perror ("reverse: "); exit (1);} charsWritten=write(out,buffer,charsRead); if (charsWritten!=charsRead){ }

Moving in a File: lseek() off_t lseek(int fd, off_t offset, int mode) Changes current file position in the file referenced by fd. offset: long integer mode describes how to interpret the offset. <stdio.h> or <unistd.h>: offset is relative to the beginning of the file (SEEK_SET), or to the current file position (SEEK_CUR), or to the end (SEEK_END) Fails if you try to move before the start of the file. Returns current file position, or -1 if fails.

lseek (fd, lines[i], SEEK_SET); charsRead = read (fd, buffer, Assume, fd is a file descriptor, lines[] is an array that holds starting positions of each line in the file. for (i = 0; i <10; i--) { int charsRead; char buffer [4096]; lseek (fd, lines[i], SEEK_SET); charsRead = read (fd, buffer, lines[i+1] - lines[i]); write (1, buffer, charsRead); }

Moving in a File: lseek() Find a current location in the file referenced by fd: lseek (fd, 0, SEEK_CUR); If you move past the end of file and perform write(), Unix automatically extends the size of the file and treats intermediate area as NULLS (0) Unix does not allocate disk area for intermediate space!! (so called “sparse” files)

Closing a File: close() int close(int fd) Closing a file descriptor releases any record locks on the file. All open files are automatically closed by the kernel when a process terminates. Returns 0, or -1 if fails. close(fd);

Deleting a File: unlink() int unlink(const char* fileName) Removes the hard link from the name fileName to its file. If it is the last link to the file, the file’s resources are deallocated. If any process’s file descriptors are currently associated with the file, the file is removed only after all of its file descriptors are closed. So executable can unlink itself during execution and still continue to completion. Returns 0 or -1, if fails. unlink(tmpfd);

Obtaining File Information: stat() int stat(const char* name, struct stat* buf) int fstat(int fd, struct stat* buf)int lstat(const char* name, struct stat* buf) Fills the buffer buf with information about file name lstat() : returns information about the symbolic link itself Returns 0 or -1, if fails

stat Structure “/usr/include/sys/stat.h” st_dev the device number st_ino the inode number st_mode the permission flags st_uid the user ID st_gid the group ID st_size the file size st_atime the last access time st_mtime the last modification time st_ctime the last status change time

Macros in /usr/include/sys/stat.h S_ISDIR(st_mode) true if directory S_ISCHR(st_mode) true if file is a character special device S_ISBLK(st_mode) true if file is a block special device S_ISREG(st_mode) true if a regular file S_ISFIFO(st_mode) true if a pipe The time fields may be decoded with the standard C library asctime() and localtime() subroutines.

Reading Directory Information: getdents() int getdents(int fd, struct dirent* buf, int structSize) Reads the directory file fd from its current position and fills structure buf with the next entry. <dirent.h>: struct dirent { long d_ino; /* inode number */ off_t d_off; /* offset to next dirent */ unsigned short d_reclen; /*length of the dirent */ char d_name [NAME_MAX+1]; /*filename+’\0’*/ } Returns the length of directory if successful, 0 if the last entry has already been read, and -1 if fails

Directory Manipulation: opendir() DIR * opendir (const char *dirname) Opens and returns a directory stream of directory dirname, or NULL, if fails. struct dirent: information about directory entries. char d_name[] is the file name+’\0’. ino_t d_fileno is the file serial number. unsigned char d_namlen is the length of the file name. unsigned char d_type is the type of the file: DT_UNKNOWN, DT_REG (regular file),DT_DIR (directory), DT_FIFO (named pipe), DT_SOCK (local-domain socket), DT_CHR (character device), DT_BLK (block device)

Directory Manipulation: readdir() and closedir() struct dirent * readdir (DIR *dirstream) Reads the next entry from the directory. Returns a pointer to a structure containing information about the file. This structure is statically allocated and can be rewritten by a subsequent call. If there are no more entries or an error is detected, returns a null pointer. int closedir (DIR *dirstream) Closes the directory stream dirstream. Returns 0 or -1 if fails.

#include <stddef. h> #include <stdio #include <stddef.h> #include <stdio.h> #include <sys/types.h> #include <dirent.h> int main (void){ DIR *dp= opendir ("./"); struct dirent *ep; if (dp != NULL){ while (ep = readdir (dp)) puts (ep->d_name); (void) closedir (dp); } else perror ("Couldn't open"); return 0; }

Changing File’s Permissions: chmod() int chmod (const char* fileName, int mode) int fchmod (int fd, int mode) Changes the mode of fileName to mode (specified as octal) Set user ID and set group ID flags have values 4000 and 2000, respectively. int main() { int flag; flag = chmod("test.txt",0600); if (flag == -1) perror("problem setting mode"); }

Process Management Process is a unique instance of a running or a runnable program. Every process in UNIX has code data a stack Parameters the address of the calling programs the return address, e. g. where to go when the function returns The automatic (local) variables a unique process ID (PID)

Init Process When UNIX starts (boots), there is only one process, called init, with PID = 1. The only way to create a new process is to duplicate an existing process. So init is the ancestor of all subsequent processes. Initially, init duplicates several times and each child process replaces its code with the code of the executable getty which is responsible for user logins. init PID =1 Child getty PID=4 Child getty PID =5

Parent and Child Processes It is common for a parent process to suspend itself until one of its child processes terminates. For example, execution in the foreground: Parent process PID 34 running shell fork() Child process PID=35 running shell PID 34 running shell, waiting for a child exec() wait() PID=35 running utility exit() signal PID 34 running shell, awakens PID=35 terminates

Creating a New Process: fork() pit_t fork(void) Causes a process to duplicate The child process inherits a copy of its parent's code, data, stack, open file descriptors, and signal tables The only difference is in the PID and parent process ID (PPID) If fork() succeeds, it returns the PID of the child to the parent process and 0 to the child process. If fork() fails, it returns a -1 to the parent process and the child process is not created.

Getting PID and PPID: getpid() and getppid() pid_t getpid(void) Returns the PID pid_t getppid(void) Returns the PPID They always succeed The PPID value for process with PID=1 is 1

Orphan Process: PPID becomes 1

Terminating a Process: exit() void exit(int status) Closes all of a process' file descriptors, deallocates its code, data, and stack; then terminates the process. When a child process terminates, it sends its parent a SIGCHLD signal and waits for its termination code (status) to be accepted. Only lower 8 bits of status are used; so value is 0-255. A process which is waiting for its parent process to accept its return code is called a zombie process. A parent accepts a child's termination code by executing wait(). The kernel ensures that all children of terminating process are adopted by init init always accepts its children termination codes.

Example

Zombie Processes A process cannot leave the system until parent process accepts its termination code If parent process is dead; init adopts process and accepts code If the parent process is alive but is unwilling to accept the child's termination code (never executes wait()), the child process will remain a zombie process. Zombie processes do not take up system resources: No data, code, stack But use an entry in the system's fixed-size process table

Waiting for a Child: wait() pid_t wait(int *status) Causes a process to suspend until one of its child processes terminates. A successful call returns the PID of the terminated child process, places its status code into status: If the rightmost byte is zero, the leftmost byte contains the low 8 bits of the value returned by the child's exit() or return() call Otherwise, the rightmost 7 bits are Signal Number that caused the child to terminate and the last bit is 1 if the child core is dumped. No children: wait() returns immediately with -1 Has zombies: wait() returns immediately with the status of one of the zombies.

Differentiating a Process: exec family With the exec family, a process replaces its current code data stack PID and PPID stay the same Only the code that the process is executing changes

Differentiating a Process: exec family Use the absolute or relative name of executable: int execl(const char* path, const char* arg0, ...,const char* argn, NULL) int execv(const char* path, const char* argv[ ]) Use $PATH variable to find the executable: int execlp(const char* path, const char* arg0, ...,const char* argn, NULL) int execvp(const char* path, const char* argv[ ]) Replaces the calling process’ code, data and stack by those of the executable whose pathname is in path.

Differentiating a Process: exec family execl() and execlp(): invoke executable with string arguments pointed by arg1,.. argn. arg0 should be the name of the executable itself the list of arguments should terminate with NULL. execv() and execvp(): invoke executable with string arguments pointed by argv[1],.. argv[n] argv[n+1] is NULL argv[0] should be the name of the executable itself. If executable is not found, -1 is returned Otherwise the calling process replaces its code, data, stack with executable’s,starts executing the new code

Example

Changing Directories: chdir() Every process has a current working directory which is used when processing a relative pathname A child process inherits the current working directory from its parent int chdir(const char* pathname) Sets a process' current working directory to pathname The process must have execute permission from the directory to succeed Returns -1 if fails Otherwise, 0

Example