1b - ELEC 2602 Object Oriented& Systems Programming...

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: ELEC 2602 Object Oriented & Systems Programming Module 1B Unix O.S. Support 1 Module 1B: the Unix Operating System Support Outline: UNIX File I/O Files and Directories Standard I/O Library System Data Files and Information Mod-1A stops here, Now let's continue our journey !! Acknowledgments and Disclaimer: The materials presented in this module are adopted from many textbooks, in particular, those several textbooks listed in the References contained in the course website. The instructor disclaims any copyright ownership of the materials presented in this module. The materials in this module are expected to be used by the students for personal studying purposes. 2 Kernel's Data Structure for the Whole File-System !! ~ the answer lies in the i-node structure (as briefly mentioned in p. 14 ~ 15 of Mod-1A !) disk partition partition partition filesystem boot blocks super block i-list directory blocks and data blocks i-nodei-node i-node 3 Points to Learn !! On our UNIX system, many of the mounted filesystems are mounted from disks physically connected to other hosts on the network (i.e. [Network File System] NFS mounted). Each file system is a self-contained volume with a superblock, an Inode table and the data/free blocks. [ref. back the diagram on p. 3] Block 0 is reserved for an optional bootstrap Block 1 is reserved for the superblock which is loaded into RAM at bootstrap time. The superblock contains both static data (block size, disk characteristics, layout) and dynamic data (free Inodes, last modification time). Blocks 2-n usually reserved for start of Inode table (where n is dependent on the size of the Inode table). Every file/directory has a Inode which contains details about it (e.g. size, owner) as well as the addresses of the blocks where the contents are stored. A directory file contains an array of filename and Inode number pairs (as illustrated in the next diagram). 4 Files and Directories: Filesystem Structure directory blocks and data blocks i-list 1st data block data block data block directory block 3rd data block data block directory block 2nd data block i-node i-node i-node i-node i-node number filename i-node filename number - Every i-node has a link count that contains the number of directory entries that point to the i-node; only when the link count goes to 0 can the file be deleted (i.e., data blocks released) 5 Files and Directories: Filesystem Structure (Cont'd) The other type of link is called a symbolic link The actual contents of the file (the data block) contains the name of the file that the symbolic link points to; for example: lrwxrwxrwx 1 root 7 Sep 25 07:14 lib -> usr/lib The filename in the directory entry is the three-character string lib and the 7 bytes of data in the file are usr/lib The file type in the i-node would be S_IFLNK so that the system knows that this is a symbolic link 6 Sample Prog. & Ex. 1 for i-node ! [** The exercise and sample program below were modified from: http://www.ee.ic.ac.uk/docs/Software/unix/programming/sys/intro.html] A UNIX filesystem will usually consist of several "file systems", that can be displayed by the df command. Try to enter "df" in the cygwin window, you'll see : (a) 7 (b) Now try to login our HKUEEE (SUNOS) server, and then type "df" command. You'll see :: 8 Sample Prog. & Ex. 1 for i-node ! Try to enter "ls Ri ~ | less", you'll see the i-node number of each file as recursively displayed from your HOME directory as below : 9 Sample Prog. #1 for i-node & file stat. /* Sample Program #1: Besides Unix commands, we can use the C struct "stat" to retrieve the i-node number as well as other info. about each file. */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/file.h> /* the following required for Solaris compilation */ #include <unistd.h> int main(int argc, char *argv) { 10 Sample Prog. #1 for i-node & file stat. (Cont'd) char *ctime(); /* generates time string from output of time() */ *ctime(); struct stat statbuf; /* Inode structure definition */ statbuf; char s[127]; if (argc != 2) { /* incorrect number of argument !! */ (argc sprintf(s, "Usage: %s filename", argv[0]); sprintf(s, perror(s); perror(s); exit(-1); } exit(if (stat(argv[1], &statbuf) == -1) { /* errror in retrieving the "stat" record !! */ &statbuf) stat" sprintf(s,"Unable to obtain the status of %s", argv[1]); perror(s); perror(s); exit(-1); } exit(fprintf(stdout, "\nFile %s is a ", argv[1]); fprintf(stdout, "\ /* Check File Type -- ref. to Mod-1B notes ! */ Modswitch (statbuf.st_mode & S_IFMT) { (statbuf.st_mode case S_IFREG : fprintf(stdout, "Regular file \n"); break; fprintf(stdout, case S_IFDIR : fprintf(stdout, "Directory file \n"); break; fprintf(stdout, case S_IFCHR : fprintf(stdout, "Character special file \n");break; fprintf(stdout, n");break; case S_IFBLK : fprintf(stdout, "Block special file \n"); break; fprintf(stdout, } 11 Sample Prog. #1 for i-node & file stat. (Cont'd) /* Display User ID, Group ID, file permission and size, I-node number */ Ifprintf(stdout, "\nuser-id %d, ", statbuf.st_uid); fprintf(stdout, "\ nuserstatbuf.st_uid); fprintf(stdout, "group-id %d, ", fprintf(stdout, "groupstatbuf.st_gid); statbuf.st_gid); fprintf(stdout, "permissions %o, ", statbuf.st_mode); fprintf(stdout, statbuf.st_mode); fprintf(stdout, "link(s) %d \n", fprintf(stdout, "link(s) statbuf.st_nlink); statbuf.st_nlink); fprintf(stdout, "size %d (bytes), ", statbuf.st_size); fprintf(stdout, statbuf.st_size); fprintf(stdout, "%d (blocks), ", statbuf.st_blocks); fprintf(stdout, statbuf.st_blocks); fprintf(stdout, "Inode # %d \n\n", statbuf.st_ino); fprintf(stdout, "Inode statbuf.st_ino); /* Display the File Time */ fprintf(stdout, "Time %s data was last read or modified:-\t%s", modified:- t%s", fprintf(stdout, argv[1], ctime(&statbuf.st_atime)); ctime(&statbuf.st_atime)); fprintf(stdout, "Time %s data was last modified:-\t\t%s", fprintf(stdout, modified:- t%s", argv[1], ctime(&statbuf.st_mtime)); ctime(&statbuf.st_mtime)); fprintf(stdout, "Time %s status was last changed:-\t\t%s", fprintf(stdout, changed:- t%s", argv[1], ctime(&statbuf.st_ctime)); ctime(&statbuf.st_ctime)); 12 Sample Prog. #1 for i-node & file stat. (Cont'd) /* Check for Read/Write/eXecute permission */ fprintf(stdout, "\nRead permission "); fprintf(stdout, (access(argv[1], R_OK) == 0) ? "granted\n" : "denied\n"); fprintf(stdout, "Write permission "); fprintf(stdout, (access(argv[1], W_OK) == 0) ? "granted\n" : "denied\n"); fprintf(stdout, "eXecute/search permission "); fprintf(stdout, (access(argv[1], X_OK) == 0) ? "granted\n" : "denied\n"); } /* End of main here ! */ 13 Exec. Session for Prog. #1 On successful compilation and exec. on SUNOS, Cygwin or Linux, you'll see :: 14 Files and Directories: link / unlink Functions #include <unistd.h> int link(const char *existingpath, const char *newpath); Can be used for creating a new link to an existing file (multiple directory entries point to the file's i-node) To remove a link: #include <unistd.h> int unlink(const char *pathname); A commonly used function for creating temporary files: create the file immediately unlink it, and then use the file (the file is still open!) In doing so, the temporary files won't be left over on the disk even if the program crashes or is terminated prematurely Other useful functions: remove and rename 15 Files and Directories: File Times Field st_atime st_mtime st_ctime Description last-access time of file data last-modification time of file data last-change time of i-node status Examplels read write chmod, chown option -u default -c st_mtime and st_ctime are different: modification time: when the contents of the file were last modified changed-status time: when the i-node of the file was last modified The access time and the modification time can be changed by: #include <sys/types.h> #include <utime.h> 16 int utime(const char *pathname, const struct utimbuf *times); struct utimbuf { time_t actime; /* access time */ time_t modtime; /* modification time */ } 17 Files and Directories: mkdir / rmdir Functions To create a new, empty directory: #include <sys/types.h> #include <sys/stat.h> int mkdir(const char *pathname, mode_t mode); To remove an empty directory: #include <unistd.h> #int rmdir(const char *pathname); 18 Files and Directories: Reading Directories #include <sys/types.h> #include <dirent.h> DIR *opendir(const char *pathname); struct dirent *readdir(DIR *dp); void rewinddir(DIR *dp); int closedir(DIR *dp); The dirent structure: struct dirent { ino_t d_ino; char d_name[NAME_MAX + 1]; } Other useful functions: chdir, fchdir, getcwd 19 Standard I/O Library: Overview Specified by the ANSI standard Written by Dennis Ritchie in around 1975 Handles buffer allocation and performing I/O in optimally-sized chunks Based on streams When we open/create a file with the standard I/O library, we associate a stream with a file When we open a stream, the standard I/O function fopen returns a pointer to a FILE object, which is a structure that contains: file descriptor used for doing the actual I/O a pointer to a buffer for the stream the size of the buffer a count of the number of characters currently in the buffer an error flag, etc. Three standard streams are defined: stdin, stdout, stderr (in <stdio.h>) 20 Standard I/O Library: Buffering 1. Fully Buffered: actual I/O takes place when the standard I/O buffer is filled flush: writing of a standard I/O buffer (to disk) flush can be done by calling standard I/O function fflush 2. Line Buffered: I/O takes place when a newline character is encountered on input or output however, because buffer size is fixed, actual I/O will occur if the buffer is filled 3. Unbuffered: no buffering at all; I/O takes place at once Standard practice: standard error is always unbuffered all other streams are line buffered if they refer to a terminal device (e.g., keyboard); otherwise, they are fully buffered 21 Standard I/O Library: Opening a Stream #include <stdio.h> FILE *fopen(const char *pathname, const char *type); FILE *freopen(const char *pathname, const char *type, FILE *fp); FILE *fdopen(int filedescriptor, const char *type); Type r or rb w or wb a or ab r+ or r+b or rb+ w+ or w+b or wb+ a+ or a+b or ab+ Description open for reading truncate to 0 length or create for writing append; open for writing at end of file, or create for writing open for reading and writing truncate to 0 length or create for reading and writing open or create for reading and writing at end of file int fclose (FILE *fp); 22 Standard I/O Library: Input/Output Functions #include <stdio.h> Character input and output functions (ref. Appendix B of "The C Programming Lang" book, p.246 - 247) int fgetc(FILE *fp); -- returns the next character from fp as an unsigned int; or EOF for end-of-file or error. -- equiv. to fgetc, but with different behavior for macro evaluation. -- equiv. to getc(stdin), i.e. reading the next character from standard input (keyboard). int getc(FILE *fp); int getchar(void); int fputc(int c, FILE *fp); -- writes the character c to output stream fp, and returns the character written or EOF for any error occurred. int putc(int c, FILE *fp); -- equiv. to fputc, but with different behavior for macro evaluation. int putchar(int c); -- equiv. to putc(c, stdout), i.e. writing the char. c to standard output (monitor). int ungetc(int c, FILE *fp); -- pushes c (as an unsigned int) back to the input stream fp so that it will be returned on the next read, i.e. rollback ! 23 Standard I/O Library: Input/Output Functions #include <stdio.h> String input and output functions (ref. Appendix B of "The C Programming Lang" book, p.246 - 247) char *fgets(char *buf, int n, FILE *fp); -- reads at most (n-1) from fp into buf and then terminated by `\0'; it returns buf on successful exec. or NULL for end-of-file or any error. char *gets(char *buf); -- reads the next input line from standard input into buf and then terminated by `\0'; it returns buf on successful exec. or NULL for end-of-file or any error. int fputs(const char *s, FILE *fp); -- writes the string s (no need to contain `\n') to fp; it returns a non-negative integer upon successful completion or EOF for any error. int puts(const char *s); -- writes the string s and a newline `\n' to stdout; it returns a non-negative integer upon successful completion or EOF for any error. 24 Standard I/O Library: Error Related Functions #include <stdio.h> Error testing/display functions (ref. Appendix B of "The C Prog. Lang" book, p.248) : many library functions are used to test/set certain status indicators when error or end-of-file occurs. Besides, the errno (as defined in <error.h>) provides further detail. void clearerr(FILE *fp); -- clears the EOF and error indicators for fp. int feof(FILE *fp); /* for testing */ -- returns non-zero if EOF is reached for fp. int ferror(FILE *fp); /* for testing */ -- returns non-zero if error occurs for fp. void perror(char *s); /* for display, frequently used in APUE */ -- prints the string s as an error message for the corresponding errno, equiv. to: fprintf(stderr, "%s\n", s). 25 Sample Prog. #2 for Revision ! /* Sample Program #2: modified from Example 5.2 at URL http://www.yendor.com/programming/unix/apue/mycat/fgetsfputs.c to illustrate the uses of the file I/O functions: fgets() and fputs() for copying files NOTE : a similar loop structure as in Sample Prog. 1 of Mod-1A while (fgets(...) != NULL) fputs(....) that can be useful for copying local files or network data from socket to socket/standard output ! */ #include <stdio.h> #define MAXLINE 8192 /* define a sufficiently large line buffer size */ int main(void) 26 Sample Prog. #2 Cont'd { char buf[MAXLINE]; while (fgets(buf, MAXLINE, stdin) != NULL) if (fputs(buf, stdout) == EOF) perror("output error"); /* Error testing on the stdin */ if (ferror(stdin)) perror("input error"); exit(0); } 27 Expected Output for Prog. #2 $ gcc -o fgets_fputs Mod1B-Prog2-fgets.c $ ./fgets_fputs Yet another file IO LOOOOOOOP HERE !!! Yet another file IO LOOOOOOOP HERE !!! <press CRTL-D or CRTL-C to end> 28 System Data and Information: An Overview Numerous data files required for normal operation /etc/password, /etc/group, etc. For example, the password file is used every time a user logs in to a UNIX system and every time a user executes the ls -l command (i.e. to check the real user or group ID of the current process for accessing a directory). Used to be manipulated by functions in standard I/O library. However, these files get very large and need a more efficient way to access them !? A portable & standardized programming interface is used now** 29 System Data and Information: Password File Based on a passwd structure as defined in <pwd.h> struct passwd member Description char *pw_name char *pw_passwd uid_t pw_uid gid_t pw_gid char *pw_gecos char *pw_dir char *pw_shell user name encrypted password (not used) numerical user ID numerical group ID comment field initial working directory initial shell (user program) 30 Program Interface for Passwd ! Can be accessed by: #include <sys/types.h> #include <pwd.h> struct passwd *getpwuid(uid_t uid); struct passwd *getpwnam(const char *name); If we want to "browse" through the password file a record at a time, we can use: #include <sys/types.h> #include <pwd.h> struct passwd *getpwent(void); /* get a single record */ void setpwent(void); void endpwent(void); 31 System Data and Information: Password File Shadow Passwords: To avoid brute force guessing of user passwords, the encrypted passwords are now stored in shadow password files (e.g., /etc/shadow, /etc/master.passwd) that can be read by the superuser only Some systems uses Network Information System (NIS) or Light-weight Directory Access Protocol (LDAP), e.g. NIS/YP is used for maintenance and distribution of a central directory of user and group information, hostnames, etc. the list of users for identification is placed in /etc/passwd, and secret authentication hashes in /etc/shadow. NIS adds another "global" user list which is used for identifying users on any client of the NIS domain. 32 System Data and Information: Group File Based on the group structure defined in <grp.h> struct group member char *gr_name Description group name Can be accessed by functions: #include <sys/types.h> #include <grp.h> struct group *getgrgid(gid_t gid); struct group *getgrnam(const char *name); struct group *getgrent(void); void setgrent(void); void endgrent(void); char *gr_passwd encrypted password (not used) numerical group ID int gr_gid char **gr_mem array of pointers to individual user names 33 System Data and Information: Other Data Files Data file Header C Struct hostent netent protoent Lookup functions gethostbyname, gethostbyaddr getnetbyname, getnetbyaddr getprotobyname, getprotobynumber getesrvbyname, getservbyport Description To retrieve hosts info. To retrieve networks info. protocols hosts/etc/hosts <netdb.h> /etc/networks /etc/protocols <netdb.h> <netdb.h> /etc/services <netdb.h> servent services Two data files for keeping login accounting info: utmp: all currently logged in users wtmp: all logins and logouts 34 System Data and Information: System ID #include <sys/utsname.h> int uname(struct utsname *name); struct utsname { char sysname[9]; /* name of the operating system */ char nodename[9]; /* name of this node */ char release[9]; /* current release of operating system */ char version[9]; /* current version of this release */ char machine[9]; /* name of hardware type */ } Berkeley-derived UNIX systems (or descendants of the "Berkeley Software Distribution" (BSD)) provide the gethostname function to return just the name of the host: #include <unistd.h> int gethostname(char *name, int namelength); 35 System Data and Information: Time/Date Functions The basic time service provided by the UNIX kernel is to count the number of seconds that have passed since the Epoch: 00:00:00 January 1, 1970, UTC These seconds are represented in a time_t system data type. The time function returns the current time and date: #include <time.h> time_t time(time_t *calendar_ptr); For convenience, we can use the following 4 functions to convert the seconds into proper format: localtime mktime ctime strftime 36 System Data and Information: Time/Date Functions(for format conv.) string asctime formatted string strftime struct tm ctime gmtime (broken-down time) localtime mktime time_t time (calendar time) kernel 37 System Data and Information: Data/Time Functions #include <time.h> struct tm *gmtime(const time_t *calptr); struct tm *localtime(const time_t *calptr); time_t mktime(struct tm *tmptr); char *asctime(const struct tm *tmptr); char *ctime(const time_t *calptr); size_t strftime(char *buf, size_t maxsize, const char *format, const struct tm *tmptr); 38 System Data and Information: Data/Time Functions The above time functions make use of the tm structure as below: struct tm { /* a broken-down time */ int tm_sec; /* seconds after the minute: [0, 61] */ int tm_min; /* minutes after the hour: [0, 59] */ int tm_hour; /* hours after midnight: [0, 23] */ int tm_mday; /* day of the month: [1, 31] */ int tm_mon; /* month of the year: [0, 11] */ int tm_year; /* years since 1980 */ int tm_wday; /* days since Sunday: [0, 6] */ int tm_yday; /* days since January 1: [0, 365] */ int tm_isdst; /* daylight saving time flag: <0, 0, >0 */ } 39 A Note of Caution : Calendar Time vs. CPU Time... 1. 2. As stated on p.19 of the APUE book, 2 different types of time values are maintained by Unix systems. Calendar time (ref. p. 35 ~ 39) [equiv. to wall-clock time] time value in seconds since 00:00:00 Jan 1, 1970 or other formats; CPU/Process time time value in clock ticks to precisely measure the central processor resources used by a single process. By def., CPU time = user CPU time + system CPU time where user CPU time is the time for executing user instructions inside a program; system CPU time is the time for system I/O or device services requested by the program. 40 Sample Prog. #3 /* Sample Program #3 : to display the ~ machine info. (inclu. machine name & O.S. Versions) - using uname(), (inclu. uname(), ~ user info. (inclu. user name & group) - using getpwuid(), (inclu. getpwuid(), ~ the calendar as well as local time functions of the machine logged in */ #include <sys/types.h> <sys/types.h> #include <sys/utsname.h> <sys/utsname.h> #include <pwd.h> <pwd.h> #include <stddef.h> <stddef.h> #include <stdio.h> <stdio.h> #include <time.h> <time.h> #define MAX_BUF_SZ 80 int main() { struct utsname *p; struct passwd *pw_ptr; pw_ptr; time_t x; *tm_ptr; struct tm *tm_ptr; char buf[MAX_BUF_SZ]; buf[MAX_BUF_SZ]; 41 Sample Prog. #3 (Cont'd) /* to display the personal user info. !! */ if ((pw_ptr = getpwnam("vtam")) == NULL) { fprintf(stderr, "Error in calling getpwnam() !\n"); exit(-1); } else { printf("<< Personal User Info. >>\n\n"); printf("User Name : %s\n", pw_ptr->pw_name); printf("User ID : %u\n", pw_ptr->pw_uid); printf("Group ID : %u\n", pw_ptr->pw_gid); printf("Init. W.Dir : %s\n", pw_ptr->pw_dir); printf("Init. Shell : %s\n", pw_ptr->pw_shell); printf("\n----------------------------\n"); } 42 Sample Prog. #3 (Cont'd) if (time(&x) == -1) { fprintf(stderr, "Error in calling time() !\n"); exit(-1); } else { printf("<< Calendar Time Info. >>\n\n"); printf("Calendar Time: %ld sec. since the Epoch: 00:00:00 Jan 1, 1970.\n", x); tm_ptr = gmtime(&x); printf("Curr. GM Time: %d/%d (DD/MM) %d:%d:%d (HH:MM:SS)\n", tm_ptr->tm_mday, tm_ptr->tm_mon+1, tm_ptr->tm_hour, tm_ptr->tm_min, tm_ptr->tm_sec); tm_ptr = localtime(&x); printf("Local Time: %d/%d (DD/MM) %d:%d:%d (HH:MM:SS)\n", tm_ptr->tm_mday, tm_ptr->tm_mon+1, tm_ptr->tm_hour, tm_ptr->tm_min, tm_ptr->tm_sec); if (strftime(buf, MAX_BUF_SZ, "%c", tm_ptr) == 0) { fprintf(stderr, "Error in calling time() !\n"); exit(-1); } else { printf("Formated time: %s\n", buf); } printf("\n----------------------------\n"); } return 0; } 43 Execution Session of Prog. 3 ~~~~~~~~~~~END OF MODULE-1B~~~~~~~~~~~~~ 44 ...
View Full Document

This note was uploaded on 07/05/2008 for the course EEE ELEC2602 taught by Professor Dr.vincenttam during the Winter '08 term at HKU.

Ask a homework question - tutors are online