[<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]
 Упражнения

Вводное упражнение
Напишите  программу,  которая  входит  в  бесконечный  цикл  и  издает
звуковой сигнал  на вашем  терминале каждый  раз, когда  вы  нажимаете
<DELETE>.  При   получении  SIGQUIT,  она  должна  вывести  сообщение,
говорящее, сколько раз прозвучал сигнал, и завершиться. { signal(2) }

Мультиплексирование ввода
Напишите программу,  которая читает  из нескольких  файлов по очереди,
т.е.  после   чтения  строки  из  одного  файла,  читается  строка  из
следующего и  т.д. Если  в течение  TIME_OUT  секунд  ничего  не  было
прочитано, берется следующий файл.

Программа получает  в качестве  аргументов имена одного или нескольких
файлов, из  которых она  будет читать.  Обычно это  терминальные файлы
(т.е. /dev/ttynn),  но могут  быть файлы  и других  типов. (read(2)  с
нетерминального  устройства   может  прочитать   несколько  строк,   в
зависимости от количества требуемых байтов и длины этих строк.) Если в
одном из файлов достигнут конец файла, из него больше не читают. Когда
конец файла достигнут во всех файлах, программа завершается. Проверьте
вашу программу так:

$ multiplex /dev/tty 'tty'
{ alarm(2), signal(2), read(2) }
Командный интерпретатор shell - продолжение
Защита от сигналов, посылаемых с терминала
Если вы проходили курс UU1001, модифицируйте ваш shell, над которым вы
работали в  качестве упражнения,  так чтобы он не завершался, когда вы
генерируете сигнал  SIGINT. Вместо  этого должен  завершаться  процесс
первого плана,  а ваш  shell должен  немедленно выдавать  приглашение.
Кроме того,  предохраните команды,  исполняемые в  фоновом  режиме, от
прерывания сигналами  SIGINT и SIGQUIT. (Если вы не имеете собственной
версии этой  программы, в  вашей директории   находятся файлы shell.c,
parseline.c, promptline.c  и shell.h.  Откомпилировав их,  вы получите
простой командный  интерпретатор, способный выполнять программы в виде
порожденных процессов,  запускать фоновые  процессы  и  перенаправлять
ввод/вывод.) { signal(2) или sigset(2) или sigaction(2), longjmp(3) }
Простое управление заданиями
Если вы реализовали защиту от сигналов, модифицируйте ваш
интерпретатор shell, так чтобы обеспечить следующие возможности для
управления заданиями: SIGTSTP, посланный с клавиатуры (<CTRL Z> по
умолчанию), должен заставить основную программу перейти в фоновый
режим и возобновить исполнение. PID переведенного на фон процесса
будет выведен на stderr, и командный интерпретатор выдаст приглашение
для следующей команды. (Совет: сделайте каждый порожденный процесс
лидером группы процессов и явным образом переводите его на первый
план. Когда порожденный процесс первого плана завершается или
останавливается, переводите на первый план интерпретатор).
{ sigset(2), sigsend(2), setpgid(2), tcsetpgrp(2), waitid(2) }
shell.c:
  1      /* PRIMITIVE JOB CONTROL SHELL */
  2 #include <sys/types.h>
  3 #include <stdio.h>
  4 #include <signal.h>
  5 #include <fcntl.h>
  6 #include <setjmp.h>
  7 #include "shell.h"
  8 #include <sys/procset.h>
  9
 10 char *infile, *outfile, *appfile;
 11 struct command cmds[MAXCMDS];
 12 char bkgrnd;
 13         /* ADD - SIGNAL HANDLING DECLARATION*/
 14 pid_t cpid;
 15
 16 main(int argc,  char **argv)
 17 {
 18     register int i;
 19     char line[1024];    /*  allow large command lines  */
 20     int ncmds;
 21     char prompt[50];    /* shell prompt */
 22     int ifd, ofd;   /* for i/o file redirection */
 23          /*ADD - SIGNAL HANDLING & JOB CONTROL DECLARATIONS */
 24
 25                /*ADD - SIGNAL HANDLING*/
 26                /*ADD - JOB CONTROL*/
 27
 28     sprintf(prompt,"[%s] ", argv[0]);
 29
 30               /*ADD - SIGNAL HANDLING*/
 31
 32     while (promptline(prompt, line, sizeof(line)) > 0) {/* until
eof */
 33         if ((ncmds = parseline(line)) <= 0)
 34             continue;       /* read next line */
 35 #ifdef DEBUG
 36 {
 37     int i, j;
 38     for (i = 0; i < ncmds; i++) {
 39         for (j = 0; cmds[i].cmdargs[j] != (char *) NULL; j++)
 40             fprintf(stderr, "cmd[%d].cmdargs[%d] = %s\n",
 41                 i, j, cmds[i].cmdargs[j]);
 42         fprintf(stderr, "cmds[%d].cmdflag = %o\n", i,
cmds[i].cmdflag);
 43     }
 44 }
 45 #endif
 46
 47         for (i = 0; i < ncmds; i++) {
 48             if (!(cpid = fork())) {
 49
 50                 /* ADD -  JOB CONTROL*/
 51
 52                 /* ADD - SIGNAL HANDLING */
 53
 54                 /* ADD -  JOB CONTROL*/
 55
 56                 /* input redirection */
 57                 if ((infile != (char *) NULL) && i == 0) {
 58                     /* check for i == 0 because only */
 59                     /* first command can have input */
 60                     /* redirected */
 61                     if ((ifd = open(infile, O_RDONLY)) < 0) {
 62                         fprintf(stderr,
 63                             "%s: %s: cannot open\n",
 64                             argv[0], infile);
 65                         exit(2);
 66                     }
 67                     close(0);      /* close standard input  */
 68                     dup(ifd);       /* ifd is now stdin */
 69                     close(ifd);
 70                 }
 71
 72                 /* output redirection  */
 73                 if ((outfile != (char*)NULL) && i == ncmds-1){
 74                     /* create new file */
 75                     if ((ofd = open(outfile,
 76                      O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) {
 77                         fprintf(stderr,
 78                             "%s: %s: cannot create\n",
 79                             argv[0], outfile);
 80                         exit(2);
 81                     }
 82                     close(1);
 83                     dup(ofd);
 84                     close(ofd);
 85                 } else if ((appfile != (char *) NULL) &&
 86                     i == ncmds-1) {
 87                     if ((ofd = open(appfile,
 88                      O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) {
 89                         fprintf(stderr,
 90                             "%s: %s: cannot open\n",
 91                             argv[0], appfile);
 92                         exit(2);
 93                     }
 94                     close(1);
 95                     dup(ofd);
 96                     close(ofd);
 97                 }
 98
 99                 execvp(cmds[i].cmdargs[0], cmds[i].cmdargs);
100                 fprintf(stderr, "%s: not found\n",
101                     cmds[i].cmdargs[0]);
102                 exit(1);    /* make sure child exits */
103             } /* close child block */
104             if (!bkgrnd) {
105
106                 while (cpid != wait((int *)0))/*CHANGE for J.C
107                     ;       /*  wait for child */
108
109                            /* ADD JOB CONTROL */
110             }
111             else
112                 fprintf(stderr, "%d\n", cpid);
113         }
114
115     }  /* close while */
116 }
117
118        /* ADD - SIGNAL HANDLING & JOB CONTROL */