UNIX System: File I/O, Signals, and Processes - Prof. H. Abdel-Wahab, Study notes of Computer Science

Examples and explanations of various unix system concepts, including file i/o using open, read, write, lseek, and close functions, standard i/o using fopen, fread, fwrite, fseek, and fclose functions, unix directory structure, basic signal handling, using signals for timeouts, process creation, file sharing between processes, and executing processes. Examples of c programs illustrating these concepts.

Typology: Study notes

Pre 2010

Uploaded on 02/12/2009

koofers-user-t9o-1
koofers-user-t9o-1 🇺🇸

9 documents

1 / 17

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
UNIX Systems Programming
(lectures programs)
Part 1: UNIX File System
Low-level I/O: open, read, write, lseek, close
Example 1: append.c
main(int argc, char **argv)
{
int n, in, out;
char buf[1024];
/* Open the first file for reading */
in = open (argv[1], O_RDONLY);
/* Open the second file for writing */
out = open (argv[2], O_WRONLY | O_APPEND);
/* Copy data from the first file to the second */
while ((n = read (in, buf, sizeof(buf))) > 0)
write out, buf, n);
}
Examples of usage:
% touch t // creat empty file t
% append append.c t // copies append.c to t
% append append.c t // make another copy of append.c to t
% append t t // endlessly copies t to t !
Example 2: seeker.c
#define NSTRINGS 5
#define STRSIZE 3
char *strings[] = {
"aaa", "bbb", "ccc", "ddd", "eee"
};
main ....
{
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff

Partial preview of the text

Download UNIX System: File I/O, Signals, and Processes - Prof. H. Abdel-Wahab and more Study notes Computer Science in PDF only on Docsity!

UNIX Systems Programming

(lectures programs)

Part 1: UNIX File System

  • Low-level I/O: open, read, write, lseek, close

Example 1: append.c

main(int argc, char **argv) { int n, in, out; char buf[1024];

/* Open the first file for reading */ in = open (argv[1], O_RDONLY);

/* Open the second file for writing */ out = open (argv[2], O_WRONLY | O_APPEND);

/* Copy data from the first file to the second */ while ((n = read (in, buf, sizeof(buf))) > 0) write out, buf, n); }

Examples of usage:

% touch t // creat empty file t % append append.c t // copies append.c to t % append append.c t // make another copy of append.c to t % append t t // endlessly copies t to t!

Example 2: seeker.c #define NSTRINGS 5 #define STRSIZE 3

char *strings[] = { "aaa", "bbb", "ccc", "ddd", "eee" };

main ....

{

int fd; fd = open ( fname, O_RDWR | O_CREAT | O_TRUNC, 0666 ); for (n = 0; n < NSTRINGS; n++) write(fd, strings[n], STRSIZE);

/* user provides the value of n */

lseek ( fd, (n-1) * STRSIZE, SEEK_SET );

read ( fd, buf, STRSIZE ); write(1, buf, STRSIZE);

}

  • Standard I/O: fopen, fread, fwrite, fseek, fclose

Example 3: fseeker.c main .... { FILE *fp; fp = fopen(fname, "w+");

for (n = 0; n < NSTRINGS; n++) fwrite(strings[n], sizeof(char), STRSIZE, fp);

fseek(fp, (n-1) * STRSIZE, SEEK_SET);

fread(buf, sizeof(char), STRSIZE, fp);

printf("String %d = %.*s\n\n", n, STRSIZE, buf); } NOTE: you may use fdopen(fd) & fileno(fp) to convert between file pointer (fp) and file descriptor (fd).

Example: int fd; FILE *fp; fd = open ("filename", O_TRUNC | O_CREAT | O_WRONLY, 0777 ); fp = fdopen(fd, "w+"); fd = fileno(fp);

  • UNIX Directory Structure: (See next Figure)

lstat(filename, &st); outputStatInfo(filename, d->d_name, &st); } }

Part 2: Signals

  • Basic Signal Handling:

o kill (pid, sig)

To send a signal sig to a process pid (To list all available signals type: % kill -l )

o pause()

To wait for a signal

o signal (sig, handler)

To call the function handler when the signal sig occurs.

Example 6: signal1.c

main ... { signal(SIGUSR1, handler); signal(SIGUSR2, handler); for (;;) pause(); }

handler(int sig) { /* Print out what we received */ psignal(sig, "Received signal"); } Examples of usage:

% kill -l HUP INT QUIT ILL TRAP ABRT EMT FPE KILL BUS SEGV SYS PIPE ALRM TERM USR1 USR CLD PWR WINCH URG POLL STOP TSTP CONT TTIN TTOU VTALRM PROF XCPU XFSZ WAITING LWP FREEZE THAW CANCEL LOST RTMIN RTMIN+1 RTMIN+2 RTMIN+ RTMAX-3 RTMAX- RTMAX-1 RTMAX

% kill -USR1 12345 Recived signal: User Signal 1

% kill -16 12345 //signal #16 is USR Recived signal: User Signal 1

% kill -KILL 12345 Killed

  • Using Signals for Timeouts:
  • alarm (T)

To send the ALRM signal to the current process after T seconds. alarm (0) will cancel the alarm signal.

Example 7: timeout1.c main ... { signal(SIGALRM, handler); alarm (atoi(argv[1])); printf("Enter a string: "); fgets(buf, sizeof(buf), stdin); alarm(0); }

handler(int sig) { printf("inside intr hand\n"); }

Example of usage:

% timeout1 3

Example of usage:

% fork

Example 9: killparent.c This example shows that when the child kills its parent, it is inherited by the init process (pid # 1).

main ... { pid_t pid;

pid = fork();

if (pid == 0) { printf("my real parent id is: %d\n", getppid()); kill ( getppid(), 9); sleep(1); printf("my foster parent id is: %d\n", getppid());

} pause(); }

Example of usage:

% killparent

  • File Sharing between processes: (see next Figure)

Example 10: fileshare.c This example shows that both parent and child share the same file pointer. main () { int in; pid_t pid; char buf[1024];

system ("echo abc123 > junk"); in = open("junk", O_RDONLY);

pid = fork(); if (pid == 0) { read(in, buf, 3);

in = open("junk", O_RDONLY); pid = fork()) ; if (pid == 0) execl("./fileread", "fileread", 0); else execl("./fileread", "fileread", 0); } The program exec a file called: fileread.c main() { char buf[1024]; read(3, buf, 3); write(1, buf, 3); write(1,"\n", 1); }

Example 13: execsignal.c

This example shows that exec preserves some siganl settings (e.g., SIG_IGN). main() { pid_t pid;

signal(SIGINT, SIG_IGN);

pid = fork();

if (pid == 0) execl("./waitsig1", "waitsig1", 0);

else execl("./waitsig2", "waitsig2", 0);

} The exec a file called: waitsig1.c & waitsig2.c main() { pause(); }

& main() { signal(SIGINT, SIG_DFL)

pause(); } Use: % ps -a to find the pid of waitsig1 and waitsig2 and Use % kill -INT to send a INT signal to waitsig1 and waitsig

  • WAIT: for a child.

Example 14: forkexecwait.c

main() { pid_t pid; char *args[4]; int status;

pid = fork(); if (pid == 0) execl("/bin/echo", "echo", "Today's date is:", NULL);

while ( wait (&status) != pid) continue;

execl("/bin/date", "date", "+%m/%d/%y", NULL); }

Example of usage:

% forkexecwait

  • Simple Shell: wahab's shell (wsh)

Example 15: wsh.c main() { int status; pid_t pid; char command[BUFSIZ];

for (;;) { printf("wsh> "); if (fgets(command, sizeof(command), stdin) == NULL) {

for (cp = args; cp != NULL; cp++) { if (strcmp(cp, "<") == 0) { *cp++ = NULL; infile = cp; } else if (strcmp(cp, ">") == 0) { *cp++ = NULL; outfile = *cp; } } status = execute(args, infile, outfile); } }

int execute(char **args, char *infile, char *outfile) { int status; pid_t p, pid; int infd, outfd; extern int errno; infd = -1; outfd = -1;

if (infile != NULL) { if ((infd = open(infile, O_RDONLY)) < 0) { perror(infile); return(-1); } }

if (outfile != NULL) { if ((outfd = creat(outfile, 0666)) < 0) { perror(outfile); close(infd); return(-1); } }

/* Ignore keyboard signals; and SIG_CHLD signals */ signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGCHLD, SIG_IGN);

/* Start a child process*/ if ((pid = fork()) < 0)

status = -1;

if (pid == 0) {

signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGCHLD, SIG_DFL);

if (infd > 0) dup2(infd, 0);

if (outfd > 0) dup2(outfd, 1);

execvp(*args, args); perror("exec"); _exit(127); }

waitpid(pid, &status, 0);

signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGCHLD, SIG_DFL);

close(outfd); close(infd);

return(status); }

size_t bufsplit(char *buf, size_t n, char **a) { .......... } Example use: % mshell msh> ls -lt (......long listing of files .....)

--> execsignal (CTRL-C will kill the command not the shell).

pipe(pfd);

pid = fork();

if (pid == 0) { dup2(pfd[1], 1); close(pfd[1]); close(pfd[0]);

execl("/bin/date", "date", 0); }

close(pfd[1]);

read (pfd[0], line, sizeof(line)); printf("date from child is: %s\n", line);

close(pfd[0]); waitpid(pid, &status, 0); exit(0); }

Example 18: parent writes to child pipemail.c

main() { pid_t pid; int pfd[2]; int i, status; char *username;

username = cuserid(NULL);

pipe(pfd);

pid = fork();

if (pid == 0) {

dup2(pfd[0], 0); close(pfd[1]);

execl("/bin/mail", "mail", username, 0); }

close(pfd[0]);

write(pfd[1], "Greetings and salutations,\n\n", 28); write(pfd[1], "This is your program saying hello.\n", 35); write(pfd[1], "Have a nice day.\n\n", 18); write(pfd[1], "Bye.\n", 5);

close(pfd[1]); waitpid(pid, &status, 0); exit(0); }