Комментарии к коду лабораторных по Unix.

/* Это третье задание к 1-ой лабораторной - Отредактируйте prog1.c – отмените комментарии для блокировок файла (то что было закомментировано -см. в методичке)

. откомпилируйте файл заново. Собственно говоря - исходник дан преподавателем ,а наша задача состоит в том, чтобы разобраться с кодом.*/   
#include <stdio.h>   /*  standard input/output header — стандартный заголовочный файл ввода/вывода */
#include <stdlib.h> /*stdlib.h — заголовочный файл стандартной библиотеки общего назначения языка Си, который содержит в себе функции, занимающиеся выделением памяти, контроль процесса выполнения программы, преобразования типов и другие*/ 
#include <unistd.h> /* определяет различные символьные константы и типы и объявляет некоторые функции.  */
#include <sys/wait.h> /* заголовок определяет ряд символьных констант, используемых с waitpid()*/
#include <sys/file.h> /* определяет константы для операций с файлами */
#include <sys/stat.h> /* определяет структуру данных .возвращаемых функциями fstat(),lstat() и stat().*/

const char *filename = "messagebuf.dat"; /* указатель на область с именем файла. */
char  msgbuf[64]; /* выделение памяти под символьный массив динной 64 байта  */
void error_out(const char *msg) /* фукция которая не возвращает значения, но при этом получает указатель на неизменяемую  символьную область.*/
{
 perror(msg); /*  выведет сообщение о последней ошибке, произошедшей во время выполнения функции или системного вызова + переданный, определяемый программистом параметр-сообщение, например - "Опять на работает !!!!!" */
 exit(EXIT_FAILURE); /* ничего не возвращает, но требует параметр статуса выхода - любое число, соответсвующее коду ошибки, однако следует помнить, что наиболее безопасным является указание: 0 или EXIT_SUCCESSFUL при успехе и EXIT_FAILURE (не единица) при неудаче.  */
}
void child(void)
{ /*With mandatory locks we block here until  the parent unlocks the file. */
 int fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0666 /*|S_ISGID */ ); /* устанавливает связь между файлом и его переменной-дискриптором. открывается с параметром который получается путём побитного сложения констант => обладает всеми их свойствами. подробнее см -http://pubs.opengroup.org/onlinepubs/009... третий аргумент определяет параметры*/
 if (fd == -1) /* Если функция вернула -1 , то значит открыть файл не удалось. */
         error_out("parent:open");  /* выводим сообщение о том, что открыть файл не удалось и описание последней произошедшей ошибки.*/
 /*  With advisory locks we block here until  the parent unlocks the file.*/

 int r = lockf(fd, F_LOCK, 0); /*Устанавливает POSIX-блокировку на открытом файле. F_LOCK - устанавливает блокировку на файле. Только один процесс может блокировать данный файл в текущий момент времени. Если файл уже блокирован, то он будет блокирован позже, когда будет снята предыдущая блокировка.  */
 if (r == -1) /*  если блокировку установить не удалось выводим сообщение об этом деле. */
        error_out("child:lockf"); /*  */

 /* Now we know the data is valid. - теперь мы знаем что данные доступны. */
 int len = read(fd, msgbuf, sizeof(msgbuf)); /*  */
 if (len <=  0) /*  */
          error_out("client:read"); /*  */
 else
  printf("child read: %s\n",msgbuf ); /* выводим сообщение о том, что потомок читает указаный файл. */
  close(fd); /* преращаем работу с файлом */
}
void parent(int fd)
{
 /*  Read a message from console  and write the message to the file. - читаем сообщение из консоли и выводим в файл. */
 printf("Enter a message > "); /*  */
 scanf("%s", msgbuf); /*  */
 write(fd, msgbuf, sizeof(msgbuf)); /*  */
 /*  Flush the user-space buffers to the filesystem before unlocking.  - сливаем данные буфера в файл*/
 fsync(fd); /* обеспечивает запись измененных данных в файл, заданный дескриптором - функция для асинхронной записи. */
 /*  As soon as the data on the filesystem is up-to-date we can unlock the file and let the child read it.  - после того как в файловой системе обновлены мы можем разблокровать файл=> позволить процессу-потомку его прочитать.*/
 
 int r = lockf(fd, F_ULOCK, 0); /* видимо. происходит открытие доступа к файлу, благодаря параметру F_ULOCK*/
 if (r == -1) /*  */
        error_out("lockf:F_ULOCK"); /*  сообщаем об ошибке если снять блокировку с файла не получилось.*/

 close(fd); /*  */
}
int main(int argc, char *argv[]) /*  */
{
 int status = 0; /*  */
 /*  Create the file before the fork  - до того как ветвится( дословно - форкнуться ) создаём файл .*/
 int fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0666 /*|S_ISGID */ ); /*  */
 if (fd == -1) /*  */
  error_out("parent:open"); /*  */
 /*  Put an exclusive lock on the file. - блокировка файла исклучительно для одного процесса. */
 
 int r = lockf(fd, F_LOCK, 0); /* блокируем файл */
 if (r == -1)
       error_out("parent:lockf"); /*выводим сообщение об ошибке для случая если блокировка не удалась  */

/*   Now we fork with the file locked. - теперь мы создали новый процесс с заблокированным файлом. */
 pid_t pid = fork(); /*  */
 switch (pid)  /* проверяем значение которое получила данная переменная */
 {
  case -1:     error_out("main:fork"); /*  если это то выводим сообщение об ошибки*/
  case  0: /*  Run the child-only code.  - запускаем код потомка - кстати, этот раздел выполнится только для родителя, потому что только в контектсте родителя fork вернёт значение "0" => потомок не сможет породить ещё одного потомка в данной ситуации.*/ /*  */
   child(); /*  запускаем код потомка. */
  exit(0); /* завершаем процессс-потомок. */
  default:  /*  Run the parent-only code and wait for the child to finish. - здесь исполням только код родителя и ждём пока завершится потомок. */ /*  */
    parent(fd); /*   запускаем код родителя*/
  wait(&status); /* получает статус процесса-потомка. функция приостанавливает вызывающего блока до того момента пока не станет доступной статус-информация одного из завершившихся процессов-потомков данного процесса.*/
  /* Child returns non-zero status on failure. */
  printf("child status=%d\n", WEXITSTATUS(status)); /*  */
 }
 unlink(filename); /* удаляем файловый дескриптор и сам файл. */
 exit(0);/* перед завершением приложения функция вызывает ряд других функций. */
}
/* Ниже я сваливаю в кучу материал из интернета по поводу различных функций и вообще  - непонятных вещей, которые имели место в  программе */
/*  */
/* Это третье задание к 1-ой лабораторной - Отредактируйте prog1.c – отмените комментарии для блокировок файла (то что было закомментировано -см. в методичке)
 3. Редактируем child.c                                          $ vi child.c 
      ?   удалить процедуру parent()                             ... 
      ?   заменить декларацию функции error_out()  на            extern  void error_out(const char *msg); 
      ?   заменить тело main() на                               child(); return 0;  
      ?   сохранить файл                                        
. откомпилируйте файл заново. Собственно говоря - исходник дан преподавателем ,а наша задача состоит в том, чтобы разобраться с кодом.*/   
#include <stdio.h>   /*  standard input/output header — стандартный заголовочный файл ввода/вывода */
#include <stdlib.h> /*stdlib.h — заголовочный файл стандартной библиотеки общего назначения языка Си, который содержит в себе функции, занимающиеся выделением памяти, контроль процесса выполнения программы, преобразования типов и другие*/ 
#include <unistd.h> /* определяет различные символьные константы и типы и объявляет некоторые функции.  */
#include <sys/wait.h> /* заголовок определяет ряд символьных констант, используемых с waitpid()*/
#include <sys/file.h> /* определяет константы для операций с файлами */
#include <sys/stat.h> /* определяет структуру данных .возвращаемых функциями fstat(),lstat() и stat().*/

const char *filename = "messagebuf.dat"; /* указатель на область с именем файла. */
char  msgbuf[64]; /* выделение памяти под символьный массив динной 64 байта  */
extern  void error_out(const char *msg) /* фукция которая не возвращает значения, но при этом получает указатель на неизменяемую  символьную область.*/
{
 perror(msg); /*  выведет сообщение о последней ошибке, произошедшей во время выполнения функции или системного вызова + переданный, определяемый программистом параметр-сообщение, например - "Опять на работает !!!!!" */
 exit(EXIT_FAILURE); /* ничего не возвращает, но требует параметр статуса выхода - любое число, соответсвующее коду ошибки, однако следует помнить, что наиболее безопасным является указание: 0 или EXIT_SUCCESSFUL при успехе и EXIT_FAILURE (не единица) при неудаче.  */
}
void child(void)
{ /*With mandatory locks we block here until  the parent unlocks the file. */
 int fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0666 /*|S_ISGID */ ); /* устанавливает связь между файлом и его переменной-дискриптором. открывается с параметром который получается путём побитного сложения констант => обладает всеми их свойствами. подробнее см -http://pubs.opengroup.org/onlinepubs/009... третий аргумент определяет параметры*/
 if (fd == -1) /* Если функция вернула -1 , то значит открыть файл не удалось. */
         error_out("parent:open");  /* выводим сообщение о том, что открыть файл не удалось и описание последней произошедшей ошибки.*/
 /*  With advisory locks we block here until  the parent unlocks the file.*/

 int r = lockf(fd, F_LOCK, 0); /*Устанавливает POSIX-блокировку на открытом файле. F_LOCK - устанавливает блокировку на файле. Только один процесс может блокировать данный файл в текущий момент времени. Если файл уже блокирован, то он будет блокирован позже, когда будет снята предыдущая блокировка.  */
 if (r == -1) /*  если блокировку установить не удалось выводим сообщение об этом деле. */
        error_out("child:lockf"); /*  */

 /* Now we know the data is valid. - теперь мы знаем что данные доступны. */
 int len = read(fd, msgbuf, sizeof(msgbuf)); /*  */
 if (len <=  0) /*  */
          error_out("client:read"); /*  */
 else
  printf("child read: %s\n",msgbuf ); /* выводим сообщение о том, что потомок читает указаный файл. */
  close(fd); /* преращаем работу с файлом */
}
int main(int argc, char *argv[]) /*  */
{
child(); 
return 0;  
}

/* Это четвёртое задание к 1-ой лпбораторной - Разделим программу на две отдельных программы: parent.c и child.c и выполним в процессе потомке, порожденном 
процессом parent, программу child. Для этого используется системный вызов execve.(см. методичку.)

Редактируем parent.c:                                        $ vi parent.c 
      ?   удалить процедуру child()                              ... 
      ?   заменить декларацию функции error_out() на 
      ?   добавить в начале main декларацию                     extern  void error_out(const char *msg); 
      ?   заменить в main() операции в case 0: на               char *const env[] = {“PATH=.”, NULL}; 
      ?   сохранить файл */   
#include <stdio.h>   /*  standard input/output header — стандартный заголовочный файл ввода/вывода */
#include <stdlib.h> /*stdlib.h — заголовочный файл стандартной библиотеки общего назначения языка Си, который содержит в себе функции, занимающиеся выделением памяти, контроль процесса выполнения программы, преобразования типов и другие*/ 
#include <unistd.h> /* определяет различные символьные константы и типы и объявляет некоторые функции.  */
#include <sys/wait.h> /* заголовок определяет ряд символьных констант, используемых с waitpid()*/
#include <sys/file.h> /* определяет константы для операций с файлами */
#include <sys/stat.h> /* определяет структуру данных .возвращаемых функциями fstat(),lstat() и stat().*/

const char *filename = "messagebuf.dat"; /* указатель на область с именем файла. */
char  msgbuf[64]; /* выделение памяти под символьный массив динной 64 байта  */
extern  void error_out(const char *msg) /* заменить декларацию функции error_out() на extern  void error_out(const char *msg);*/
{
 perror(msg); /*  выведет сообщение о последней ошибке, произошедшей во время выполнения функции или системного вызова + переданный, определяемый программистом параметр-сообщение, например - "Опять на работает !!!!!" */
 exit(EXIT_FAILURE); /* ничего не возвращает, но требует параметр статуса выхода - любое число, соответсвующее коду ошибки, однако следует помнить, что наиболее безопасным является указание: 0 или EXIT_SUCCESSFUL при успехе и EXIT_FAILURE (не единица) при неудаче.  */
}
/*здесь удалена процедура child*/
void parent(int fd)
{
 /*  Read a message from console  and write the message to the file. - читаем сообщение из консоли и выводим в файл. */
 printf("Enter a message > "); /*  */
 scanf("%s", msgbuf); /*  */
 write(fd, msgbuf, sizeof(msgbuf)); /*  */
 /*  Flush the user-space buffers to the filesystem before unlocking.  - сливаем данные буфера в файл*/
 fsync(fd); /* обеспечивает запись измененных данных в файл, заданный дескриптором - функция для асинхронной записи. */
 /*  As soon as the data on the filesystem is up-to-date we can unlock the file and let the child read it.  - после того как в файловой системе обновлены мы можем разблокровать файл=> позволить процессу-потомку его прочитать.*/
 
 int r = lockf(fd, F_ULOCK, 0); /* видимо. происходит открытие доступа к файлу, благодаря параметру F_ULOCK*/
 if (r == -1) /*  */
        error_out("lockf:F_ULOCK"); /*  сообщаем об ошибке если снять блокировку с файла не получилось.*/

 close(fd); /*  */
}
int main(int argc, char *argv[]) /*  */
{ char *const env[] = {"PATH=.", NULL};// этот массив констант добавлен для выполнения 4-ого задания - ".....добавить в начале main декларацию." 
 int status = 0; /*  */
 /*  Create the file before the fork  - до того как ветвится( дословно - форкнуться ) создаём файл .*/
 int fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0666 /*|S_ISGID */ ); /*  */
 if (fd == -1) /*  */
  error_out("parent:open"); /*  */
 /*  Put an exclusive lock on the file. - блокировка файла исклучительно для одного процесса. */
 
 int r = lockf(fd, F_LOCK, 0); /* блокируем файл */
 if (r == -1)
       error_out("parent:lockf"); /*выводим сообщение об ошибке для случая если блокировка не удалась  */

/*   Now we fork with the file locked. - теперь мы создали новый процесс с заблокированным файлом. */
 pid_t pid = fork(); /*  */
 switch (pid)  /* проверяем значение которое получила данная переменная */
 {
  case -1:     error_out("main:fork"); /*  если это то выводим сообщение об ошибки*/
  case 0: execve("./child", NULL, env); // запускает программу ,ссылка на файл исполняемого кода которой находится в списке параметров функции передаёт есй список переменных-строк и список переменных среды окружение - второй параметр.
  default:  /*  Run the parent-only code and wait for the child to finish. - здесь исполням только код родителя и ждём пока завершится потомок. */ /*  */
    parent(fd); /*   запускаем код родителя*/
  wait(&status); /* получает статус процесса-потомка. функция приостанавливает вызывающего блока до того момента пока не станет доступной статус-информация одного из завершившихся процессов-потомков данного процесса.*/
  /* Child returns non-zero status on failure. */
  printf("child status=%d\n", WEXITSTATUS(status)); /*  */
 }
 unlink(filename); /* удаляем файловый дескриптор и сам файл. */
 exit(0);/* перед завершением приложения функция вызывает ряд других функций. */
}

/* Это третье задание к 1-ой лпбораторной - Отредактируйте prog1.c – отмените комментарии для блокировок файла (то что было закомментировано -см. в методичке)

. откомпилируйте файл заново. Собственно говоря - исходник дан преподавателем ,а наша задача состоит в том, чтобы разобраться с кодом.
4. Редактируем errmsg.c                                         $ vi child.c 
      ?   удалить все функции, кроме error_out()                 ... 
      ?   сохранить файл                                         :wq */   
#include <stdio.h>   /*  standard input/output header — стандартный заголовочный файл ввода/вывода */
#include <stdlib.h> /*stdlib.h — заголовочный файл стандартной библиотеки общего назначения языка Си, который содержит в себе функции, занимающиеся выделением памяти, контроль процесса выполнения программы, преобразования типов и другие*/ 
#include <unistd.h> /* определяет различные символьные константы и типы и объявляет некоторые функции.  */
#include <sys/wait.h> /* заголовок определяет ряд символьных констант, используемых с waitpid()*/
#include <sys/file.h> /* определяет константы для операций с файлами */
#include <sys/stat.h> /* определяет структуру данных .возвращаемых функциями fstat(),lstat() и stat().*/

const char *filename = "messagebuf.dat"; /* указатель на область с именем файла. */
char  msgbuf[64]; /* выделение памяти под символьный массив динной 64 байта  */
void error_out(const char *msg) /* фукция которая не возвращает значения, но при этом получает указатель на неизменяемую  символьную область.*/
{
 perror(msg); /*  выведет сообщение о последней ошибке, произошедшей во время выполнения функции или системного вызова + переданный, определяемый программистом параметр-сообщение, например - "Опять на работает !!!!!" */
 exit(EXIT_FAILURE); /* ничего не возвращает, но требует параметр статуса выхода - любое число, соответсвующее коду ошибки, однако следует помнить, что наиболее безопасным является указание: 0 или EXIT_SUCCESSFUL при успехе и EXIT_FAILURE (не единица) при неудаче.  */
}
void child(void)
{ /*With mandatory locks we block here until  the parent unlocks the file. */
 int fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0666 /*|S_ISGID */ ); /* устанавливает связь между файлом и его переменной-дискриптором. открывается с параметром который получается путём побитного сложения констант => обладает всеми их свойствами. подробнее см -http://pubs.opengroup.org/onlinepubs/009... третий аргумент определяет параметры*/
 if (fd == -1) /* Если функция вернула -1 , то значит открыть файл не удалось. */
         error_out("parent:open");  /* выводим сообщение о том, что открыть файл не удалось и описание последней произошедшей ошибки.*/
 /*  With advisory locks we block here until  the parent unlocks the file.*/

 int r = lockf(fd, F_LOCK, 0); /*Устанавливает POSIX-блокировку на открытом файле. F_LOCK - устанавливает блокировку на файле. Только один процесс может блокировать данный файл в текущий момент времени. Если файл уже блокирован, то он будет блокирован позже, когда будет снята предыдущая блокировка.  */
 if (r == -1) /*  если блокировку установить не удалось выводим сообщение об этом деле. */
        error_out("child:lockf"); /*  */

 /* Now we know the data is valid. - теперь мы знаем что данные доступны. */
 int len = read(fd, msgbuf, sizeof(msgbuf)); /*  */
 if (len <=  0) /*  */
          error_out("client:read"); /*  */
 else
  printf("child read: %s\n",msgbuf ); /* выводим сообщение о том, что потомок читает указаный файл. */
  close(fd); /* преращаем работу с файлом */
}
void parent(int fd)
{
 /*  Read a message from console  and write the message to the file. - читаем сообщение из консоли и выводим в файл. */
 printf("Enter a message > "); /*  */
 scanf("%s", msgbuf); /*  */
 write(fd, msgbuf, sizeof(msgbuf)); /*  */
 /*  Flush the user-space buffers to the filesystem before unlocking.  - сливаем данные буфера в файл*/
 fsync(fd); /* обеспечивает запись измененных данных в файл, заданный дескриптором - функция для асинхронной записи. */
 /*  As soon as the data on the filesystem is up-to-date we can unlock the file and let the child read it.  - после того как в файловой системе обновлены мы можем разблокровать файл=> позволить процессу-потомку его прочитать.*/
 
 int r = lockf(fd, F_ULOCK, 0); /* видимо. происходит открытие доступа к файлу, благодаря параметру F_ULOCK*/
 if (r == -1) /*  */
        error_out("lockf:F_ULOCK"); /*  сообщаем об ошибке если снять блокировку с файла не получилось.*/

 close(fd); /*  */
}
int main(int argc, char *argv[]) /*  */
{
 int status = 0; /*  */
 /*  Create the file before the fork  - до того как ветвится( дословно - форкнуться ) создаём файл .*/
 int fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 0666 /*|S_ISGID */ ); /*  */
 if (fd == -1) /*  */
  error_out("parent:open"); /*  */
 /*  Put an exclusive lock on the file. - блокировка файла исклучительно для одного процесса. */
 
 int r = lockf(fd, F_LOCK, 0); /* блокируем файл */
 if (r == -1)
       error_out("parent:lockf"); /*выводим сообщение об ошибке для случая если блокировка не удалась  */

/*   Now we fork with the file locked. - теперь мы создали новый процесс с заблокированным файлом. */
 pid_t pid = fork(); /*  */
 switch (pid)  /* проверяем значение которое получила данная переменная */
 {
  case -1:     error_out("main:fork"); /*  если это то выводим сообщение об ошибки*/
  case  0: /*  Run the child-only code.  - запускаем код потомка - кстати, этот раздел выполнится только для родителя, потому что только в контектсте родителя fork вернёт значение "0" => потомок не сможет породить ещё одного потомка в данной ситуации.*/ /*  */
   child(); /*  запускаем код потомка. */
  exit(0); /* завершаем процессс-потомок. */
  default:  /*  Run the parent-only code and wait for the child to finish. - здесь исполням только код родителя и ждём пока завершится потомок. */ /*  */
    parent(fd); /*   запускаем код родителя*/
  wait(&status); /* получает статус процесса-потомка. функция приостанавливает вызывающего блока до того момента пока не станет доступной статус-информация одного из завершившихся процессов-потомков данного процесса.*/
  /* Child returns non-zero status on failure. */
  printf("child status=%d\n", WEXITSTATUS(status)); /*  */
 }
 unlink(filename); /* удаляем файловый дескриптор и сам файл. */
 exit(0);/* перед завершением приложения функция вызывает ряд других функций. */
}

Makefile =

CC=gcc
PROGS=parent child
CFLAGS=-Wall
all: $(PROGS)
child: child.c errmsg.o
parent: parent.c errmsg.o
$(CC) $(CFLAGS) parent.c errmsg.o -o parent
errmsg.o: errmsg.c
$(CC) $(CFLAGS) -c errmsg.c -o errmsg.o
clean:
rm -f *.o
rm -f *.so
rm -f *.a
rm -f $(PROGS)

===============================это всё по первой лабе. конец 1-ой=============================

Comments

/* ниже идёт список макросов с их описанием.
Макросы - это препроцессорные "функции" , т.е. лексемы, созданные с помощью директивы #define, которые принимают параметры подобно функциям.
Лексема - единица текста программы, которая при компиляции воспринимается как единое целое и по смыслу не может быть разделена на более мелкие элементы.
 в том числе отсюда - http://www.linux4me.org/viewtopic.php?f=...
	•   WIFEXITED(status) - возвращает истинное значение, если потомок нормально завершился, то есть вызвал exit(3) или _exit(2), или вернулся из
функции main().
     •   WEXITSTATUS(status) - возвращает код завершения потомка. Он состоит из восьми младших бит аргумента status, который потомок указал при вызове
exit(3) или _exit(2) или в аргументе оператора return в функции main(). Этот макрос можно использовать, только если
WIFEXITED вернул истинное значение.
     •   WIFSIGNALED(status) - возвращает истинное значение, если потомок завершился из-за сигнала.
     •   WTERMSIG(status) - возвращает номер сигнала, который привел к завершению потомка. Этот макрос можно использовать, только если WIFSIGNALED
вернул истинное значение.
     •   WCOREDUMP(status) - возвращает истинное значение, если потомок создал дамп памяти (core dump). Данный макрос должен использоваться только,
если при WIFSIGNALED возвращается истинное значение. Данный макрос не указан в POSIX.1-2001 и недоступен в некоторых
реализациях UNIX (например, AIX, SunOS). Используйте его обрамлённым #ifdef WCOREDUMP ... #endif.
     •   WIFSTOPPED(status) - возвращает истинное значение, если потомок остановлен по сигналу; это возможно только, если при вызове был указан флаг
WUNTRACED или если над потомком выполняется трассировка .
     •   WSTOPSIG(status) - возвращает номер сигнала, из-за которого потомок был остановлен. Этот макрос можно использовать только, если при WIF?
STOPPED возвращается истинное значение.
     •   WIFCONTINUED(status) -(начиная с Linux 2.6.10) возвращает истинное значение, если потомок продолжил работу, получив сигнал SIGCONT. */
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
int main (void)
{
int status;
pid_t pid;
if (!fork ( )) // порождаем новый процесс  - пример неявного приведения результата функции к булевому типу.
return 1;
pid = wait (&status); // ждём завершения потомка.
if (pid == -1)
perror ("wait");
printf ("pid=%d\n", pid);
if (WIFEXITED (status))
printf ("Normal termination with exit status=%d\n", WEXITSTATUS (status)); // нормальное завершение с возвращаемым статусом
if (WIFSIGNALED (status))
printf ("Killed by signal=%d%s\n",WTERMSIG (status),
WCOREDUMP (status) ? " (dumped core)" : "");
if (WIFSTOPPED (status))
printf ("Stopped by signal=%d\n",WSTOPSIG (status));
if (WIFCONTINUED (status))
printf ("Continued\n");
return 0;
/* abort(); */
}
/* ниже идёт список макросов с их описанием.
Макросы - это препроцессорные "функции" , т.е. лексемы, созданные с помощью директивы #define, которые принимают параметры подобно функциям.
Лексема - единица текста программы, которая при компиляции воспринимается как единое целое и по смыслу не может быть разделена на более мелкие элементы.
 в том числе отсюда - http://www.linux4me.org/viewtopic.php?f=...
	•   WIFEXITED(status) - возвращает истинное значение, если потомок нормально завершился, то есть вызвал exit(3) или _exit(2), или вернулся из
функции main().
     •   WEXITSTATUS(status) - возвращает код завершения потомка. Он состоит из восьми младших бит аргумента status, который потомок указал при вызове
exit(3) или _exit(2) или в аргументе оператора return в функции main(). Этот макрос можно использовать, только если
WIFEXITED вернул истинное значение.
     •   WIFSIGNALED(status) - возвращает истинное значение, если потомок завершился из-за сигнала.
     •   WTERMSIG(status) - возвращает номер сигнала, который привел к завершению потомка. Этот макрос можно использовать, только если WIFSIGNALED
вернул истинное значение.
     •   WCOREDUMP(status) - возвращает истинное значение, если потомок создал дамп памяти (core dump). Данный макрос должен использоваться только,
если при WIFSIGNALED возвращается истинное значение. Данный макрос не указан в POSIX.1-2001 и недоступен в некоторых
реализациях UNIX (например, AIX, SunOS). Используйте его обрамлённым #ifdef WCOREDUMP ... #endif.
     •   WIFSTOPPED(status) - возвращает истинное значение, если потомок остановлен по сигналу; это возможно только, если при вызове был указан флаг
WUNTRACED или если над потомком выполняется трассировка .
     •   WSTOPSIG(status) - возвращает номер сигнала, из-за которого потомок был остановлен. Этот макрос можно использовать только, если при WIF?
STOPPED возвращается истинное значение.
     •   WIFCONTINUED(status) -(начиная с Linux 2.6.10) возвращает истинное значение, если потомок продолжил работу, получив сигнал SIGCONT. */
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
int main (void)
{
int status;
pid_t pid;
if (!fork ( )) // порождаем новый процесс  - пример неявного приведения результата функции к булевому типу.
return 1;
pid = wait (&status); // ждём завершения потомка.
if (pid == -1)
perror ("wait");
printf ("pid=%d\n", pid);
if (WIFEXITED (status))
printf ("Normal termination with exit status=%d\n", WEXITSTATUS (status)); // нормальное завершение с возвращаемым статусом
if (WIFSIGNALED (status))
printf ("Killed by signal=%d%s\n",WTERMSIG (status),
WCOREDUMP (status) ? " (dumped core)" : "");
if (WIFSTOPPED (status))
printf ("Stopped by signal=%d\n",WSTOPSIG (status));
if (WIFCONTINUED (status))
printf ("Continued\n");
abort();  /* как системный вызов exit(2) - Функции exit и _exit завершают вызванный процесс. Перед за-
вершением процесса функция exit обновляет все буферы и закрывает
все открытые файлы. Функция _exit завершает все процессы без об-
новления буферов потока.

Функция abort работает так же, как системный вызов exit(2),
 но вместо просто выхода (завершения процесса) abort посылает сигнал SIGABRT (6) вызывающему процессу.
 Если сигнал SIGABRT не перехватывается и не игнорируется, то прежде, чем он будет послан, выталкиваются все буфера,
 связанные со стандартным пакетом ввода/вывода stdio(3S), и порождается файл с образом памяти.
Функция abort возвращает значение системного вызова kill(2). */
}
/* функция значение описание.*/
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
    pid_t pid;
    char *message;
    int n;
    printf("fork program starting\n"); // о порождении нового процесса.
    pid = fork();
    switch(pid)
    {
     case -1:
               perror("fork failed");
               exit(1);
     case 0:
               message = "This is the child";  /* Только потомок */
               n = 15;
               break;
     default:
               message = "This is the parent"; /* Только родитель */
               n = 10;
               break;
    }
    /* Общий код для родителя и потомка */
    for(; n > 0; n--) {
           puts(message); /* Эта функция записывает выбранную строку string в стандартный поток вывода stdout, заменяя в выходном потоке нулевой символ
окончания строки ('') символом новой строки ('n').
Функция puts возвращает последний записанный символ, кото-
рым обычно является символ новой строки 'n'. Значение EOF свиде-
тельствует об ошибке.
См. также fputs, gets.
*/
           sleep(1);// кратко - пристанавливае выполнение программы на указанное количество секунд. 
    }
    exit(0);
}

===================это всё есть по второй.=========================

_________ _ _ ______
dthcbz фкн вгу and co

/* http://wiki.kryukov.biz/wiki/%D0%A1%D0%B...
Сигнал TERM(15) посылается программе, если необходимо завершить ее выполнение. При получении этого сигнала программа выполняет все необходимые действия для завершения работы: закрывает соединения, открытые файлы, сохраняет данные. В общем, корректно завершает свою работу. */
/* сразу хочу сказать ,что "убивать" потомка не надо  -надо просто завершить его выполнение системой процесса- а не его жизнь, заметьте - мы просто завершаем ряд действий системы - сам же процесс в теперешнем его состоянии никогда не сможет "жить" самостоятельно -он не облажает возможностью к саморазвитию - и по существу является просто действием, ничего не производяшим - это сложный вопрос - но всё же - дело в том, что такие понятия как это сейчас активно пытаются перетянуть на людей - чтобы можно было "завершать" их - а относительно людей как не назови - это убийство . на мой взгляд не стоит делать понятие "убийства"  -чем-то естественным и простым. такая вольность с терминами является моральной подготовкой к вещам хужшим . никого не надо убивать.
* pkill.c — Послать сигнал процессу, используя команду kill(1)

Системный вызов  waitpid() блокирует выполнение текущего процесса до тех пор, пока либо не завершится порожденный им процесс, определяемый значением параметра pid, либо пока текущий процесс не получит сигнал, для которого установлена реакция по умолчанию "завершить процесс" или реакция обработки пользовательской функцией. Если порожденный процесс, заданный параметром pid, к моменту системного вызова находится в состоянии закончил исполнение, системный вызов возвращается немедленно без блокирования текущего процесса. http://cs.mipt.ru/docs/courses/osstud/ma...
*/


#include <sys/types.h>
#include <wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
  pid_t child;
  char str[20];
  if((child = fork()) < 0) /*  если новый процесс породить  не удалось */
  {
    perror("fork");
    exit(EXIT_FAILURE);
  }
 else if(child == 0) /*  если удалось и это контекст процесса потомка (смотри принцип действия fork) */ 
 { /* в процессе потомке — просто спим */
   sleep(30); /*  останавливаем выполнение не меньше чем столько вот секунд - но эта пауза будет прервана завершением, как видно из дальнейшего контекста - */
 } 
 else  /* */
 { /* в процессе родителе — завершаем  потомка */
   sprintf(str, "%d", child); /*Функция sprintf форматирует и запоминает наборы символов и значений в str . %d - подразумевает int-формат*/
   printf("killing %s\n", str);
   if((execl("/bin/kill", "/bin/kill", str, NULL)) < 0)  /* вот здесь мы и посылаем потомку завершающий сигнал обновляя (насколько я понимаю) контескт родителя.*/ 
   { /* при сбое exec, ожидаем завершения потомка и получаем статус */
     perror("execl");
     waitpid(child, NULL, 0); /*  */
     exit(EXIT_FAILURE);/* парамерт демонстрирует неудачное завершение процесса родителя  */
   }
  /* printf("000", str);*/
  }
exit(EXIT_FAILURE); /* не должны бы здесь оказаться */
}
/*описание функции значение. */

/* сразу хочу сказать ,что "убивать" потомка не надо  -надо просто завершить его выполнение системой процесса- а не его жизнь, заметьте - мы просто завершаем ряд действий системы - сам же процесс в теперешнем его состоянии никогда не сможет "жить" самостоятельно -он не облажает возможностью к саморазвитию - и по существу является просто действием, ничего не производяшим - это сложный вопрос - но всё же - дело в том, что такие понятия как это сейчас активно пытаются перетянуть на людей - чтобы можно было "завершать" их - а относительно людей как не назови - это убийство . на мой взгляд не стоит делать понятие "убийства"  -чем-то естественным и простым. такая вольность с терминами является моральной подготовкой к вещам хужшим . никого не надо убивать.
* pkill.c — Послать сигнал процессу, используя команду kill(1)

Системный вызов  waitpid() блокирует выполнение текущего процесса до тех пор, пока либо не завершится порожденный им процесс, определяемый значением параметра pid, либо пока текущий процесс не получит сигнал, для которого установлена реакция по умолчанию "завершить процесс" или реакция обработки пользовательской функцией. Если порожденный процесс, заданный параметром pid, к моменту системного вызова находится в состоянии закончил исполнение, системный вызов возвращается немедленно без блокирования текущего процесса. http://cs.mipt.ru/docs/courses/osstud/ma...
*/


#include <sys/types.h>
#include <wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
  pid_t child;
  char str[20];
  if((child = fork()) < 0) /*  если новый процесс породить  не удалось */
  {
    perror("fork");
    exit(EXIT_FAILURE);
  }
 else if(child == 0) /*  если удалось и это контекст процесса потомка (смотри принцип действия fork) */ 
 { 
 /* в процессе потомке — завершаем  выполнение родителя */
   printf("child is starting with pid =  %d\n", getpid());
sprintf(str, "%d", getppid()); /*Функция sprintf форматирует и запоминает наборы символов и значений в str . %d - подразумевает int-формат*/
   printf("killing %s\n", str); 
   if((execl("/bin/kill", "/bin/kill", str, NULL)) < 0)  /* вот здесь мы и посылаем потомку завершающий сигнал обновляя (насколько я понимаю) контескт родителя.*/ 
   { /* при сбое exec, ожидаем завершения потомка и получаем статус */
     perror("execl");
     exit(EXIT_FAILURE);/* парамерт демонстрирует неудачное завершение процесса потомка  */
   }
 } 
 else  /* */
 {  /* приостанавливаем выполнение процесса-родителя */
   printf("parent is starting with pid =  %d\n", getpid());
   sleep(30); /*  останавливаем выполнение не меньше чем столько вот секунд - но эта пауза будет прервана завершением, как видно из дальнейшего контекста - */
 }
exit(EXIT_FAILURE); /* не должны бы здесь оказаться */
}
/*описание функции значение. */

/* здесь не будем использовать обновление контекста завершающего процеса, а просто пошлём завершаемому процессу сигналЮ, что позволит нам в дальнейшем узнать новый parent-pid потомка, после завершения родителя сигналом.
*/


#include <sys/types.h>
#include <wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
 
  pid_t child;
  char str[20];
  if((child = fork()) < 0) /*  если новый процесс породить  не удалось */
  {
    perror("fork");
    exit(EXIT_FAILURE);
  }
 else if(child == 0) /*  если удалось и это контекст процесса потомка (смотри принцип действия fork) */ 
 { 
 /* в процессе потомке — завершаем  выполнение родителя */
  printf("child is starting with pid =  %d\n", getpid());
  if ( kill(getppid(), SIGTERM)<0) { perror("kill:SIGTERM");}
  else
  { printf("parent is stoped know \n");
sleep(1); /* ждём, иначе может выйти так, что следуюяя команда выводящяя навый parent-pid выполнится раньше чем завершится радитель и потомок будет передан в наследники другому процессу - видимо, это связано с тем .что процесс выполняются параллельно  -в смысле. что нельзя предсказать - какой из них закончится раньше  */ 
    printf("the new child's parent had pid= %d\n",getppid());
  }

 } 
 else  /* */
 {  /* приостанавливаем выполнение процесса-родителя */
   printf("parent is starting with pid =  %d\n", getpid());
   sleep(30); /*  останавливаем выполнение не меньше чем столько вот секунд - но эта пауза будет прервана завершением, как видно из дальнейшего контекста - */
 }
exit(EXIT_FAILURE); /* не должны бы здесь оказаться */
}
/* сигнал функция описание значение */
/* системный вызов kill(2)
 http://ru.wikipedia.org/wiki/SIGCHLD
http://webcache.googleusercontent.com/se...

SIGCHLD - посылается процессу в том случае, если его дочерний процесс завершился или был приостановлен. Родительский процесс также получит этот сигнал, если он установил режим отслеживания сигналов дочернего процесса и дочерний процесс получил какой-либо сигнал. По умолчанию сигнал SIGCHLD игнорируется. 

*/
#include <sys/types.h>
#include <wait.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
  pid_t child;
  int errret;
  if((child = fork()) < 0)
  {
  perror("fork");
  exit(EXIT_FAILURE);
  } 
  else if(child == 0) 
  { /* в процессе потомке */
  printf("child is starting with pid =  %d\n", getpid());
  sleep(30);
  } 
  else 
  { /* в процессе родителе */ 
      printf("parent is starting with pid =  %d\n", getpid());
			/* посылаем сигнал, который игнорируется */
			printf("sending SIGCHLD to %d\n", child);
      sleep(1);   /*немного ждём  - иначе, как показывает практика  потомок просто не успевает вывести сообщение о том, что он запущён, как уже прерывается */ 
			errret = kill(child, SIGCHLD); /* В POSIX-системах SIGCHLD — сигнал, посылаемый при изменении статуса дочернего процесса (завершен, приостановлен или        возобновлен*/ 
			if(errret < 0)
			perror("kill:SIGCHLD");
			else
			printf("%d still alive\n", child);
			/* теперь убиваем потомка */
			printf("killing %d\n", child);
			if((kill(child, SIGTERM)) < 0)
			perror("kill:SIGTERM");
			/* ожидаем для получения статуса завершения */
			waitpid(child, NULL, 0 );
	}
	exit(EXIT_SUCCESS);
}

/* сигнал функция описание значение */
/* системный вызов kill(2)
 http://ru.wikipedia.org/wiki/SIGCHLD
http://webcache.googleusercontent.com/se...

SIGCHLD - посылается процессу в том случае, если его дочерний процесс завершился или был приостановлен. Родительский процесс также получит этот сигнал, если он установил режим отслеживания сигналов дочернего процесса и дочерний процесс получил какой-либо сигнал. По умолчанию сигнал SIGCHLD игнорируется. 

*/
#include <sys/types.h>
#include <wait.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
  pid_t child;
  int errret;
  if((child = fork()) < 0)
  {
  perror("fork");
  exit(EXIT_FAILURE);
  } 
  else if(child == 0) 
  { /* в процессе потомке */
  printf("child is starting with pid =  %d\n", getpid());
 
			/*завершаем родителя */
			printf("killing %d\n", getppid());
			if((kill(getppid(), SIGTERM)) < 0)
			perror("kill:SIGTERM");
		  printf("parent is stoped know \n");
      sleep(1); // немного ждём чтобы сигнал возымел своё действие на родителя.
      printf("the new child's parent had pid= %d\n",getppid()); 

  } 
  else 
  { /* в процессе родителе */ 
      printf("parent is starting with pid =  %d\n", getpid());
			/* просто ждём*/
			sleep(30);
	}
	exit(EXIT_SUCCESS);
}

/* http://www.cs.ifmo.ru/education/document...
* mysleep.c — примитивное моделирование функции sleep(1)
http://valera.asf.ru/perl/help/name.php?...

Программы, обычно используют SIGALRM при реализации тайм-аута для долговременной опрерации, или выполнения операции через определённые интервалы.
SIGALRM посылается ядром через целое количество секунд после вызова alarm(). Иногда этот механизм используется для реализации функции sleep().

Функция alarm предназначена для планирования генерации сигнала SIGALARM.Этот сигнал будет передан процессу через указанное в качестве аргумента количество секунд. Если аргумент не указан, будет использоваться значение переменной $_.

*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
/* Установить будильник */
sleep(1);
if((alarm(5)) > 0)
printf("an alarm was already set"); else puts("know we set the alarm - there wasn't any before.");
/* Засыпаем достаточно на долго, чтобы сработал будильник */
sleep(30);
/* Не должны бы оказаться здесь! */
puts("how did we get here?");
exit(EXIT_FAILURE);
}
/*each signal has an associated default handler (or action). In the case of SIGALRM  that action is to terminate the process. You can change this default action (for most signals) by registering a signal handler of your own or assigning SIG_IGN (ignore). 
 
Действие SIGALRM 
каждый сигнал имеет ассоциированный с ним обработчик по умолчанию, поэтому SIGALRM также имеет обработчик, который прекращает выполнение процесса, которым получен сигнал. В свою очередь, данный обработчик может быть переопределённым иным пользовательским обработчиком или же получение сигнала может быть игнорировано путем соотнесения с SIG_IGN */
/* */
/* */
/* */
/*
* pause()  - приостанавливает выполнение программы до тех пор пока не будет получен сигнал  ,который не приводит к завершеню программы  и при этом не вызввает обработчик .
*/
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
	pause();
	exit(EXIT_SUCCESS);
}

/* почему этот процесс нельзя завершить kill-ом по умолчанию. */ 
/* */
/*
*
Каждый процесс имеет собственную маску сигналов, представленную в ядре ОС битовым полем, где бит установленный в 1 соответствует номеру сигнала, который блокируется данным процессом.

http://netlib.narod.ru/library/book0010/...
работа с сигналами в линукс , кратко - http://skif.bas-net.by/bsuir/ipcbook/nod...
*/
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
void err_quit(char *);
int main(void)
{
	sigset_t newset;
	/* Создаем пустой набор  ; Множество сигналов инициализируется функцией sigemptyset(). */
	if((sigemptyset(&newset)) < 0) err_quit("sigemptyset");

	/* добавляем SIGCHLD в набор */
	if((sigaddset (&newset, SIGCHLD)) < 0)  err_quit("sigaddset");

	/* Проверяем маску сигналов */
	if(sigismember(&newset, SIGCHLD)) puts("SIGCHLD is in signal mask");
	else puts("SIGCHLD not in signal mask");
	
  /* SIGTERM не должен быть в наборе */
	if(sigismember(&newset, SIGTERM)) puts("SIGTERM in signal mask");
	else puts("SIGTERM not in signal mask");
	
  exit(EXIT_SUCCESS);
}

void err_quit(char *msg)
{
	perror(msg);
	exit(EXIT_FAILURE);
}


/* */
/*
*
rmset.c — Удаление сигнала из набора
*/
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
void err_quit(char *);
int main(void)
{
	sigset_t newset;
	/* Создать набор */
	if((sigfillset(&newset)) < 0) err_quit("sigfillset");
	
 /* Удалить SIGALRM из набора */
	if((sigdelset(&newset, SIGALRM)) <0) err_quit("sigaddset");
	
  /* SIGALRM не должен быть */
	if(sigismember (&newset, SIGALRM)) puts("SIGALRM is in signal mask");
	else puts("SIGALRM not in signal mask");
	
  /* SIGTERM должен остаться в наборе */
	if(sigismember(&newset, SIGTERM)) puts("SIGTERM in signal mask");
	else puts("SIGTERM not in signal mask");
	
  exit(EXIT_SUCCESS);
}
void err_quit(char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
/* */
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
void err_quit(char *);
int main(void)
{
	sigset_t newset;
	/* создаем новый набор */
	if((sigemptyset(&newset)) < 0)
	err_quit("sigemptyset");

	/* Добавляем SIGTERM и SIGALRM */
	if((sigaddset(&newset, SIGTERM)) < 0)
	err_quit("sigaddset:SIGTERM");
	if((sigaddset(&newset, SIGALRM)) < 0)
	err_quit("sigaddset:SIGALRM");

	/* Блокируем эти сигналы без их специальной обработки */
	if((sigprocmask(SIG_BLOCK, &newset, NULL)) < 0)
	err_quit("sigprocmask");

	/* Ожидаем сигнал */
	pause();
	exit(EXIT_SUCCESS);
}
void err_quit(char *msg)
{
	perror(msg);
	exit(EXIT_FAILURE);
}

/*#
#
#
#
Откройте второе окно терминала (putty) и выполните команды:
ps -al  найдите процесс программы block - кстати, что это за ключ такой  "-al" - отпишитесь если кто знает.
kill -TERM $(pidof ./block)  = с block ничего не происходит
kill -ALRM $(pidof ./block)  = с block ничего не происходит
kill -QUIT $(pidof ./block)  = а этот сигнал не блокируется и завершает процесс!
 */
/*В POSIX-системах, SIGUSR1 и SIGUSR2 — пользовательские сигналы, которые могут быть использованы для межпроцессной синхронизации и управления.

Системный вызов sigaction используется для изменения действий процесса при получении соответствующего сигнала.  */

#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
void err_quit(char *); /* функция сообщения об ошибке */
void hndl_usr1(int); /* обработчик сигнала */
int main(void)
{
	struct sigaction action;
	/* Устанавливаем обработчик сигнала */
	action.sa_handler = hndl_usr1;
	sigemptyset(&action.sa_mask);
	action.sa_flags = SA_NOCLDSTOP;
	/* Регистрируем обработчик сигнала */
	if((sigaction(SIGUSR1, &action, NULL)) < 0)
	err_quit("sigaction");
	/* Достаточно времени, чтобы послать сигнал */
	sleep(300);
	exit(EXIT_SUCCESS);
	}
	void err_quit(char *msg)
	{
	perror(msg);
	exit(EXIT_FAILURE);
}
void hndl_usr1(int signum) /* это функция-обработчик сигнала*/
{
if(signum == SIGUSR1)
puts("caught USR1");
else
printf("caught %d\n", signum); // эта строчка по-моему не выполнится в даннос случае так как  функция hndl_usr1() вызывается  только  в случае получения SIGUSR1 - если я не прав - просьба исправить)
}

/*Выполните в другом окне
# ps -al
# kill -USR1 $(pidof ./block)
 */

============Конец третьей лабы =====================

_________ _ _ ______
dthcbz фкн вгу and co

5-ая лабораторная (перед ней можете разместить четвёртую прокомментировав предыдущий пост (тоже комментарий)))

/*
5-ая лабораторная (перед ней можете разместить четвёртую прокомментировав предыдущий пост (тоже комментарий)))
http://toggetit.livejournal.com/5009.html
http://rus-linux.net/lib.php?name=/MyLDP...
http://skif.bas-net.by/bsuir/ipcbook/nod...
http://cs.mipt.ru/docs/courses/osstud/ma...
 Команды / операции
? >
? <
? >>
? |
? history - выводит историю сообщений.
? grep - осуществляет поиск в файле строк ,  соответствующих  заданному шаблону (шаблон задаёмтся правее самой программы.) и .
? sort - сортирует список "слов" в алфавитном порядке, а с опцией -u удаляет дубликаты. 
? tail - Команда tail копирует указанный файл на стандартный вывод, начиная с определенного места. Если файл не задан, то используется стандартный ввод. example% tail -15cf fred - выводит последние 15 байтов файла fred ; example% tail -f fred  - выводит последние 15 строк файла фред (хотя здесь я не уверен - см. ключи команды - см. ссылку - http://www.opennet.ru/man.shtml?topic=gr...) 

? mknod - Команда mknod создает элемент каталога и описатель для специального файла. 
? mkfifo -   Функция mkfifo предназначена для создания FIFO в операционной системе. 
    Параметр path является указателем на строку, содержащую полное или относительное имя файла, который будет являться меткой FIFO на диске. Для успешного создания FIFO файла с таким именем перед вызовом функции не должно существовать.
---------
Системные вызовы и функции
? dup - int dup (int fildes) ; - Аргумент fildes - это дескриптор файла, полученный после выполнения системных вызовов creat, open, dup, fcntl и pipe. Системный вызов dup возвращает новый дескриптор файла, имеющий следующие общие свойства с исходным дескриптором:

   1. Тот же открытый файл (или канал).
   2. Тот же указатель текущей позиции в файле (то есть оба дескриптора разделяют один и тот же указатель).
   3. Тот же режим доступа (чтение, запись или чтение/запись). 

? dup2 - #include<io.h> int dup2(int oldhandle, int newhandle); dup2 создает    новый   дескриптор   со   значение newhandle  Если  файл  связанный   с   дескриптором newhandle   открыт,   то   при   вызове   dup2   он закрывается.


? (неименованный)pipe int pipe(int filedes[2]); pipe создает пару файловых описателей, указывающих на запись inode именованного канала, и помещает их в массив, на который указывает filedes. filedes[0] предназначен для чтения, а filedes[1] предназначен для записи. 
 
? popen =     FILE *popen(const char* command, const char* mode); 
Параметр command соответствует системному вызову команды, которая выполняет некоторую программу. Между процессом пользователя и вызванным процессом устанавливается труба для обмена информацией. Режим работы трубы устанавливается параметром mode. "r" означает чтение из трубы, а "w" - запись в трубу. В случае ошибки создания трубы popen() возвращает NULL, иначе возвращается указатель файла. Таким образом, функция popen() выполняет следующие действия: 
    * Вызов pipe():
    * Вызов fork() (Создание процесса-потомка);
    * Закрытие ненужных дескрипторов в родителе и потомке;
    * Замену процесса-потомка с помощью exec.

? mknod -int mknod (path, mode, dev) Системный вызов mknod создает новый файл с маршрутным именем, на которое указывает аргумент path. Режим нового файла определяется аргументом mode.
 
? (создание именнованного канала.)mkfifo int = mkfifo(char *path, int mode); 


    Функция mkfifo предназначена для создания FIFO в операционной системе. 

    Параметр path является указателем на строку, содержащую полное или относительное имя файла, который будет являться меткой FIFO на диске. Для успешного создания FIFO файла с таким именем перед вызовом функции не должно существовать.
    Параметр mode устанавливает атрибуты прав доступа различных категорий пользователей к FIFO. Этот параметр задается как некоторая сумма следующих восьмеричных значений:

    0400 	- Разрешено чтение для пользователя, создавшего FIFO.
    0200 	- Разрешена запись для пользователя, создавшего FIFO.
    0040 	- Разрешено чтение для группы пользователя, создавшего FIFO.
    0020 	- Разрешена запись для группы пользователя, создавшего FIFO.
    0004 	- Разрешено чтение для всех остальных пользователей
    0002 	- Разрешена запись для всех остальных пользователей

    При создании FIFO реально устанавливаемые права доступа получаются из стандартной комбинации параметра mode и маски создания файлов текущего процесса umask, а именно - они равны  mode & ~umask.

    При успешном создании FIFO функция возвращает значение 0, при неуспешном - отрицательное значение. 
--------------------
 Команда первая: wget получает содержимое HTML web страницы.
Команда вторая: sed удаляет из текста страницы все символы, не являющиеся пробелами или буквами и заменяет их пробелами.
Команда третья: tr переводит все символы верхнего регистра в нижний регистр (заглавные буквы в строчные), а также конвертирует пробелы в строках в символы новой строки, так что теперь каждое "слово" является новой строкой.

*/

=========================================

#include <unistd.h>
int main(int argc, char *argv[])
{
char buf;
while (read(STDIN_FILENO, &buf, 1) > 0)
write(STDOUT_FILENO, &buf, 1);
}
/*STDIN_FILENO определяет дескриптор файла для стандартного ввода, а STDOUT_FILENO - для стандартного вывода. */

====================================

/*open/creat1 – открыть/создать файл с заданными опциями и режимом доступа
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
*/

#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
	char buf;
	int fd_IN, fd_OUT;

	if (argc == 2)
	{
		fd_IN = open(argv[1], O_RDONLY, 0644);
		close(0); // закрываем стандартный ввод. 
		dup(fd_IN);/* Теперь одинаково: стандартный ввод или ввод из файла ВОЗВРАЩАЕТСЯ НАИМЕНЬШИЙ ИЗ ДОСТУПНЫХ ДЕСКРИПТОРОВ, СООТВЕТСТВЕННО ЗДЕСЬ  - 0 -то есть наш стандартный ввод.*/
	
  }
		while (read(STDIN_FILENO, &buf, 1) > 0)
		write(STDOUT_FILENO, &buf, 1);

}
 /* см. сюда - http://lord-n.narod.ru/download/books/wa...
Вот простой пример использования аргумента командной строки. На экран выводятся слово Привет и ваше имя, которое надо указать в виде аргумента командной строки.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  if(argc!=2) {
    printf("Вы забыли ввести свое имя.\n");
    exit(1);
  }
  printf("Привет %s", argv[1]);

  return 0;
}

Если вы назвали эту программу name (имя) и ваше имя Том, то для запуска программы следует в командную строку ввести name Том. В результате выполнения программы на экране появится сообщение Привет, Том. 
*/

===========================

/*open/creat1 – открыть/создать файл с заданными опциями и режимом доступа
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
*/

#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
	char buf;
	int fd_IN, fd_OUT;

	if (argc == 2)
	{
		fd_IN = open(argv[1], O_RDONLY, 0644);
		close(0); // закрываем стандартный ввод. 
		dup(fd_IN);/* Теперь одинаково: стандартный ввод или ввод из файла ВОЗВРАЩАЕТСЯ НАИМЕНЬШИЙ ИЗ ДОСТУПНЫХ ДЕСКРИПТОРОВ, СООТВЕТСТВЕННО ЗДЕСЬ  - 0 -то есть наш стандартный ввод.*/
	
  }
	if (argc == 3)
		{
			fd_IN = open(argv[1], O_RDONLY, 0644);
      fd_OUT = open(argv[2], O_WRONLY, 0644);
			close(0); // закрываем стандартный ввод. 
			dup(fd_IN);/* Теперь одинаково: стандартный ввод или ввод из файла ВОЗВРАЩАЕТСЯ НАИМЕНЬШИЙ ИЗ ДОСТУПНЫХ ДЕСКРИПТОРОВ, СООТВЕТСТВЕННО ЗДЕСЬ  - 0 -то есть наш стандартный ввод.*/
	    close(1); // закрываем стандартный вывод. 
			dup(fd_OUT);
		}
 
		while (read(STDIN_FILENO, &buf, 1) > 0)
		write(STDOUT_FILENO, &buf, 1);

}
 /* см. сюда - http://lord-n.narod.ru/download/books/wa...
Вот простой пример использования аргумента командной строки. На экран выводятся слово Привет и ваше имя, которое надо указать в виде аргумента командной строки.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  if(argc!=2) {
    printf("Вы забыли ввести свое имя.\n");
    exit(1);
  }
  printf("Привет %s", argv[1]);

  return 0;
}

Если вы назвали эту программу name (имя) и ваше имя Том, то для запуска программы следует в командную строку ввести name Том. В результате выполнения программы на экране появится сообщение Привет, Том. 
*/

================================

/* Два родственных процесса должны закрыть противоположные концы канала для использования
оставшихся открытыми файловых дескрипторов для коммуникации в соответствующем
направлении.
*/
#include <sys/wait.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
	int pfd[2];
	pid_t cpid;
	char buf;
	assert(argc == 2); /* проверка на сооответствие - если условие не выполнено  -программа будет завершена.*/
	if (pipe(pfd) == -1) { perror("pipe"); exit(EXIT_FAILURE); }
  
	cpid = fork();
	if (cpid == -1) { perror("fork"); exit(EXIT_FAILURE); }
	if (cpid == 0) 
  {
		close(pfd[1]); /* Закрывает неиспользуемый write канала*/

    puts("child is reading :");/* Потомок - читает из канала*/
		while (read(pfd[0], &buf, 1) > 0)
		write(STDOUT_FILENO, &buf, 1);
		write(STDOUT_FILENO, "\n", 1);
		close(pfd[0]); 	/* закрывает второй конец кнала после использования*/
		_exit(EXIT_SUCCESS);
	} 
  else
  {
		/* Родитель – записывает argv[1] в канал */
		close(pfd[0]); /* Закрывает неиспользуемый read канала */
    printf("parent is writing =  %s\n", argv[1]);
		/* Закрывает неиспользуемый read канала */
		write(pfd[1], argv[1], strlen(argv[1])); /* Родитель – записывает argv[1] в канал */
		close(pfd[1]); 	/* закрывает второй конец кнала после использования*/
		/* читатель увидит EOF */
		wait(NULL);
		/* ожидает завершения потомка */
		exit(EXIT_SUCCESS);
	}
}

/* */

======================это всё, что есть по 5-ой===========

_________ _ _ ______
dthcbz фкн вгу and co

/*   http://www.codenet.ru/progr/cpp/spru/sta...

               int stat(pathname, buffer);
               char *pathname;       path-имя существующего файла
               struct stat *buffer;  указатель на строку, принимающую
                                     результаты
  
     Функция stat получает информацию о  файле  или  директории,
         определенном по pathname, и запоминает ее в структуре, на которую
         указывает  buffer.  
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
int main (int argc, char *argv[]) /* Имя файла передается в командной строке */
{
	struct stat sb;
	int ret;
	if (argc < 2) 
	{
		fprintf (stderr, "usage: %s <file>\n", argv[0]); /*Поток номер 2 (stderr) зарезервирован для вывода диагностических и отладочных сообщений в текстовом виде.*/
		return 1; 
	}

	ret = stat (argv[1], &sb); /* формируем структуру с данными о файле*/

	if (ret) 
	{
		perror ("stat");
		return 1;
	}
	printf ("%s is %ld bytes\n", argv[1], sb.st_size);
	return 0;
}




/* Структура stat, объявленная в   <sys\stat.h>, содержит следующие поля:

              struct stat {

dev_t st_dev;  устройство, на котором расположен файл 
ino_t st_ino;  номер индексного узла для файла 
mode_t st_mode;  тип файла и права доступа к нему 
nlink_t st_nlink; / счетчик числа жестких связей /
uid_t st_uid; / идентификатор пользователя владельца /
gid_t st_gid; / идентификатор группы владельца /
dev_t st_rdev; / тип устройства для специальных файлов устройств /
off_t st_size; / размер файла в байтах (если определен для данного типа файлов) /
unsigbed long st_blksize; / размер блока для файловой системы /
unsigned long st_blocks; / число выделенных блоков /
time_t st_atime; / время последнего доступа к файлу /
time_t st_mtime; /время последней модификации файла /
time_t st_ctime; / время создания файла /

}

               Возвращаемое значение.
            
               Функция  stat возвращает значение 0, если получена информа-
         ция о статусе файла. Возвращаемое значение -1 свидетельствует  об
         ошибке,  и  errno  устанавливается  в  ENOENT, т.е. имя файла или
         path-имя не найдено.

----------------------------------------------------------------------------

 Каждый файл файловой системы UNIX 
описывается метаданными в структуре inode, являющейся элементом массива i-list 
определенного размера. Собственно блоки с данными файла определяются ссылками в 
структуре inode  файла и блоками косвенности.
При создании нового файла, создается соответствующая структура inode, которая сохраняется в 
первом свободном элементе массива i-list на диске. Обратите внимание, что имя файла не */


/* struct ext2_inode {
        __le16  i_mode;           режим доступа к файлу 
        __le16  i_uid;               идентификатор владельца UID
        __le32  i_size;              размер файла в байтах 
        __le32  i_atime;           время последнего доступа 
        __le32  i_ctime;          время создания 
        __le32  i_mtime;         время последней модификации
        __le32  i_dtime;         время удаления 
        __le16  i_gid;             идентификатор группы владельца GUID 
        __le16  i_links_count;   счетчик жестких ссылок 
        __le32  i_blocks;         счетчик блоков 
        __le32  i_flags;         контрольные флаги файла 
       …
       __le32  i_block[EXT2_N_BLOCKS];  указатели на блоки с данными 
      ...
}
При создании нового файла, создается соответствующая структура inode, которая сохраняется в
первом свободном элементе массива i-list на диске. Обратите внимание, что имя файла не
включается в структуру inode, вместо этого, структура данных для директория связывает имя
файла с индексом inode в i-list, который называется индексным дескриптором файла
struct ext2_dir_entry_2 {
__le32 inode; индексный дескриптор inode
__le16 rec_len; размер записи в директории
__u8 name_len; длина имени 
__u8 file_type; 
char name[EXT2_NAME_LEN]; имя файла 
};

*/

========================

/*ino_t st_ino;  номер индексного узла для файла 
Синтаксис fstat        #include <sys\stat.h>
                       int fstat(char * handle, struct stat * buff)
Функция fstat  записывают  информацию  об  открытом
                   файле  (или  директории),  связанным с дескриптором
                   handle в структуру  stat.  Aргумент  buff  адресует
                   структуру  stat  (определенную в файле sys\stat.h).

*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
int get_inode (int fd)
{
	struct stat buf;
	int ret;
	ret = fstat (fd, &buf);
	if (ret < 0) {
	perror ("fstat");
	return -1;
  }
	return buf.st_ino;
}
int main (int argc, char *argv[])
{
	int fd, inode;
	if (argc < 2)
   {
	fprintf (stderr, "usage: %s <file>\n", argv[0]);
	return 1;
	}
	fd = open (argv[1], O_RDONLY);
	if (fd < 0) {
	perror ("open");
	return 1;
	}
	inode = get_inode (fd);
	printf ("%d\n", inode);
	return 0;
}

================================

/*Проверьте работу следующей функции
которая проверяет, располагается ли файл, указанный параметром fd на физическом диске (возвращает
положительное целое) или на виртуальном, сетевом устройстве (возвращает 0). При ошибке, возвращает -1.

*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

int is_on_physical_device (int fd)
{ int rez;
	struct stat sb;
	int ret;
	ret = fstat (fd, &sb);
	if (ret) {
	perror ("fstat");
	return -1;
	}
	rez=gnu_dev_major (sb.st_dev);
   printf ("//////// %d\n", rez);
  return rez;
}
int main (int argc, char *argv[])
{ int is_on_physical_device (int fd);
	int fd, ind;
	if (argc < 2)
  {
		fprintf (stderr, "usage: %s <file>\n", argv[0]);
		return 1;
	}
	fd = open (argv[1], O_RDONLY);
	if (fd < 0) 
  {
		perror ("open");
		return 1;
	}

	ind = is_on_physical_device (fd);
	if (ind == -1)
  puts ("При попытке определить место положения файла произошла ошибка (error here)");
  if (ind == 0)
  puts ("Указанный вами файл располагается на виртуальном носителе. функуия проверки вернула ноль.");
  if (ind >0)
  printf ("Указанный вами файл %s\n располагается на физическом диске. функция проверки вернула %d\n", argv[1],  ind);
return 0;
}
/*
http://manual.cream.org/index.cgi/gnu_de...

#include _BSD_SOURCE 

#define <sys/types.h> 

dev_t makedev(int maj, int min);

int major(dev_t dev); int minor(dev_t dev); 









 Структура stat, объявленная в   <sys\stat.h>, содержит следующие поля:

              struct stat {

dev_t st_dev;  устройство, на котором расположен файл 

ino_t st_ino;  номер индексного узла для файла 
mode_t st_mode;  тип файла и права доступа к нему 
nlink_t st_nlink; / счетчик числа жестких связей /
uid_t st_uid; / идентификатор пользователя владельца /
gid_t st_gid; / идентификатор группы владельца /
dev_t st_rdev; / тип устройства для специальных файлов устройств /
off_t st_size; / размер файла в байтах (если определен для данного типа файлов) /
unsigbed long st_blksize; / размер блока для файловой системы /
unsigned long st_blocks; / число выделенных блоков /
time_t st_atime; / время последнего доступа к файлу /
time_t st_mtime; /время последней модификации файла /
time_t st_ctime; / время создания файла /

*/

===================всё по 6-ой==================

_________ _ _ ______
dthcbz фкн вгу and co

/*
Создает и инциализирует сегмент общей памяти=
  Передача сообщений через очередь, рассмотренная в предыдущем параграфе, хотя и позволяет
избежать использования ресурсов файловой системы, но требует копирования сообщений из
буферов памяти в области пользователя в область ядра при записи, и обратно, при чтении.
  Разделяемая память позволяет наиболее эффективно обмениваться информацией различным
процессам в системе, поскольку все процессы «присоединенные» к участку разделяемой памяти
имеют прямой доступ для чтения и записи в этот участок.

*/
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFSZ 4096
int main(void)
{
int shmid;
if((shmid = shmget(IPC_PRIVATE, BUFSZ, 0666)) < 0) /*возвращающим идентификатор участка разделяемой памяти, указанного размера size в байтах и
инициализирующим структуру данных ядра*/
 {
perror("shmget");
exit(EXIT_FAILURE);
}
printf("segment created: %d\n", shmid);
system("ipcs -m"); /*передача параметра в качестве системной команды*/
exit(EXIT_SUCCESS);
}





/*

----------------
В реализации UNIX System V от AT&T2 в ядро системы были добавлены специальные средства
для обеспечения коммуникации между процессами, выполняющимися на одной машине.3 Идея
заключалась в использовании адресного пространства ядра, разделяемого между всеми
процессами в системе, для построения структур данных и интерфейсов доступа к ним через
специальные системные вызовы для взаимодействующих процессов. Такие средства получили
название IPC4,это
• очереди сообщений — для взаимодействия процессов через расширенный вариант FIFO структуры;
• разделяемая память — для общего доступа к страницам памяти из разных процессов;
• семафоры — средства синхронизации доступа к разделяемым ресурсам.
 ------------------------------
Создание любого IPC средства следует одной и той же логике:

• поскольку средство должно быть доступно всем процессам, то оно представляется
структурами данных ядра;
• для уникальной идентификации ресурса он создается и подключается
взаимодействующими процессами с помощью уникального ключа типа key_t, известного
только взаимодействующим процессам и ядру;
• все средства IPC имеют собственный уникальный идентификатор id, генерируемый
ядром по заданному ключу при создании ресурса (системными вызовами msgget/2,
shmget/2, semget/2) и используемый взаимодействующими процессами в других
системных вызовах для обращения к ресурсу.

*/

================

/*http://cs.mipt.ru/docs/courses/osstud/ma...
struct shmid_ds {
    struct ipc_perm shm_perm;  /* права на выполнение операции 
    int shm_segsz;             /* размер сегмента (в байтах) 
    time_t shm_atime;          /* время последнего подключения 
    time_t shm_dtime;          /* время последнего отключения 
    time_t shm_ctime;          /* время последнего изменения структуры 
    unsigned short shm_cpid;   /* идентификатор процесса создателя 
    unsigned short shm_lpid;   /* идентификатор процесса, подключавшегося последним 
    short shm_nattch;          /* количество текущих подключений сегмента 
    ...
};
*/
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
	int shmid; /* Идентификатор сегмента */
	char *shmbuf; /* Адрес в адресном пространстве процесса */
	if(argc != 2) { /* id сегмента должно передаваться в командной строке */
	puts(" не был указан идентификатор сегмента общей памяти ! USAGE: atshm <identifier>");
	exit(EXIT_FAILURE);
	}
	shmid = atoi(argv[1]);
	if((shmbuf = shmat(shmid, 0, 0)) < (char *)0) { /* Присоединение сегмента  Системный вызов shmat предназначен для включения области разделяемой памяти в адресное пространство текущего процесса. */
	perror("shmat");
	exit(EXIT_FAILURE);
	}
	printf(" Сегмент присоединён к  - segment attached at %p\n", shmbuf); /* Где он реально присоединен? */
	system("ipcs -m"); /* Проверим присоединение! */
	if((shmdt(shmbuf)) < 0) { /* Отсединяем - Системный вызов shmdt предназначен для исключения области разделяемой памяти из адресного пространства текущего процесса. */
	perror("shmdt");
	exit(EXIT_FAILURE);
	}
	puts(" Сегмент  отсоединён -  segment detached\n");
	system("ipcs -m"); /* Приверим отсоединение */
	exit(EXIT_SUCCESS);
}

==============================

/*http://read.pudn.com/downloads151/source... */

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#define BUFSZ 4096
int main(int argc, char *argv[])
{
		int shmid; /* ID сегмента */
		char *shmbuf; /* Адрес в адресном пространстве процесса */
		int fd; /* Файловый дескриптор */
		int i;
		/* Счетчик */
		if(argc != 2) { /* id сегмента должно передаваться в командной строке */
		puts("USAGE: opshm <identifier>");
		exit (EXIT_FAILURE);
		}

		shmid = atoi(argv[1]);
		if((shmbuf = shmat(shmid, 0, 0)) < (char *)0) { /* Присоединяем сегмент */
		perror("shmat");
		exit(EXIT_FAILURE);
		}
		if((shmbuf = malloc(sizeof(char) * BUFSZ)) == NULL) { /* Резервируем память для shmbuf */
		perror("malloc");
		exit(EXIT_FAILURE);
		}
		for(i = 0; i < BUFSZ; ++i)  /*  набиваем сегмент общей памяти  данными в цикле */
		shmbuf[i] = i % 127;  /*  %- Определение остатка от деления */
		fd = open("opshm.out", O_CREAT | O_WRONLY, 0600); /* записываем данные из сегмента общей памяти в файл */
		write(fd, shmbuf, BUFSZ);
		exit(EXIT_SUCCESS);
}

==========================

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
void error_out(const char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[])
{ int status;
	key_t mykey = 12345678; /* ключ для использования сегмента общей памяти */
	const size_t region_size = sysconf(_SC_PAGE_SIZE); /* Используется сегмен в одну страницу */

	/* Создание сегмента общей памяти */
	int smid = shmget(mykey, region_size, IPC_CREAT | 0666);
	if (smid == -1) error_out("shmget");
	/* Присоединение сегмента общей памяти */
	void *ptr;
	ptr = shmat(smid, NULL, 0); /* Присоединение сегмента общей памяти */
	if (ptr == (void *) -1)
	error_out("shmat");

	pid_t pid = fork(); /* Порождение нового процесса */
	if (pid == 0) 
		{/* Процесс потомок наследует отображение памяти */
		u_long *d = (u_long *) ptr;
		*d = 0xdeadbeef; /* потомок производи запись данных в сегмент */
		exit(0);
	}
	else
  {
	/* Синхронизация с потомком через waitpid */
	int status;
	waitpid(pid, &status, 0);

	/* Родитель использует значение из общей памяти */
	printf("child wrote %#lx\n", *(u_long *) ptr);
	}
	/* По окончании, отсоединяем сегмент */
	int r = shmdt(ptr);
	if (r == -1)
	error_out("shmdt");
	/* Удаляем сегмент из ресурсов ядра */
	r = shmctl(smid, IPC_RMID, NULL);
	if (r == -1)
	error_out("shmdt");
	return 0;
}

============================

/* msgget - получает идентификатор очереди сообщений*/
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
	int qid; /* Идентификатор очереди */
	key_t key; /* Ключ очереди */
	key = 123;
	if((qid == msgget(key, IPC_CREAT | 0666)) < 0) /* Создание очереди - Для создания или подключения к очереди сообщений используется вызов msgget/2 */
	{
		perror("msgget:create");
		exit(EXIT_FAILURE);
	}
	printf(" очередь создана - created queue id = %d\n", qid);

	if((qid == msgget(key, 0)) < 0) /* Открыть очередь еще раз */
	{
		perror("msgget:open");
		exit(EXIT_FAILURE);
	}
	printf("процесс открыл созданную ранее очередь - opened queue id = %d\n", qid);
	exit (EXIT_SUCCESS);
}
/* http://cs.mipt.ru/docs/courses/osstud/ma... 
   http://www.codenet.ru/progr/cpp/spru/fge...

 Запись в ранее созданную очередь сообщений
char *fgets(string, n, stream);читает  строку  из  потока stream.

Функция  fgets  читает  строку  из входного потока stream и
         располагает ее в string. Символы считываются, начиная  с  текущей
         позиции stream, до символа новой строки '\n'  или до конца потока,
         либо пока число считанных символов не станет равным n-1.*/
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define BUFSZ 512
struct msg
 {                                              /*определите id очереди сообщений = "ipcs -q" */
	/* Структура сообщения */
	long msg_type;
	char msg_text[BUFSZ];
};
int main(int argc, char *argv[])
{
	int qid;/* Идентификатор очереди */
	int len; /* Размер сообщения */
	struct msg pmsg; /* Указатель на сообщение */
	if(argc != 2) 
	{
		/* ID должен быть передан в командной строке */
		puts(" id очереди не указан ! USAGE: qsnd <queue ID>");
		exit(EXIT_FAILURE);
	}
	qid = atoi(argv[1]); /*Функция atoi() преобразует строку, адресуемую параметром str, в значение типа int. Эта строка должна содержать допустимое целое число. В противном случае возвращаемое значение не определено.*/
	puts(" Введите текст сообщения = Enter message to post:");
	/* Получить сообщение для записи в очередь */
	if((fgets((&pmsg) ->msg_text, BUFSZ, stdin)) == NULL)
  {
		puts(" добавить сообщение не вышло = no message to post");
		exit(EXIT_SUCCESS);
	}
	pmsg.msg_type = getpid(); /* Связать тип сообщения с pid процесса */
	len = strlen(pmsg.msg_text);
	/* Добавить сообщение в очередь */
	if((msgsnd(qid, &pmsg, len, 0)) < 0) /*Системный вызов msgsnd  предназначен для помещения сообщения в очередь сообщений*/
  {
		perror("msgsnd");
		exit(EXIT_FAILURE);
	}
	puts(" сообщение добавлено в очередь ! = message posted");
	exit(EXIT_SUCCESS);
}

===============добавляйте материалы и заметки по 7-ой ниже==================

_________ _ _ ______
dthcbz фкн вгу and co

/* int pthread_create (pthread_t *restrict thread, const pthread_attr_t *restrict attr,
void *(*start_routine)(void*), void *restrict arg);
где
thread – уникальный идентификатор созданной нити,
attr - атрибуты нити, (может быть NULL),
start_routine – указатель на функцию для выполнения в данном потоке,
arg- структура данных, определяющая параметр функции start_routine.
----------------------
pthread_t pthread_self(void); - этим вызовом нить может узнать свой собственный идентификатор.
*/
/*
* C Code for fork() creation test
*/
#include <stdio.h>
#include <stdlib.h>
#define NFORKS 1000
void do_nothing() 
{
	int i;
	i= 0;
}
int main(int argc, char *argv[]) 
{
	int pid, j, status;
	for (j=0; j<NFORKS; j++) {
	/*** error handling ***/
	if ((pid = fork()) < 0 ) {
	printf ("fork failed with error code= %d\n", pid);
	exit(0);
	}
	/*** this is the child of the fork ***/
	else if (pid ==0) {
	do_nothing();
	exit(0);
	}
	/*** this is the parent of the fork ***/
	else {
	waitpid(pid, status, 0);
}
}
}




/* Кроме общего адресного пространства, нити используют еще следующие общие атрибуты
контекста процесса, внутри которого они существуют:

• идентификатор процесса PID и идентификатор родительского процесса PPID;
• идентификаторы группы процесса и сеанса;
• управляющий терминал;
• права и владельцев процесса (UID и GID);
• таблицу открытых файлов процесса;
• записи блокировок файлов, порожденные fcntl/2;
• диспозицию сигналов;
• информацию о файловой системе: umask, домашний директорий и корневой директорий;
• различные таймеры;
• состояния семафоров IPC;
• предельные значения для ресурсов;
• время использования CPU (от times);
• потребляемые ресурсы (от getusage);
• значения приоритетов (от nice и setpriority);
-------------------------------
Кроме указателя выполняемой инструкции (PC) и стека, каждая нить имеет собственные
атрибуты (контекст нити):
• идентификатор нити;
• маску сигналов;
• специальные данные нити;
• альтернативный стек сигналов (см. sugaltstack/2);
• переменную errno;
• среду обработки операций с плавающей точкой (см. fenv/3);
• политику и приоритет планировщика реального времени выполнения;
• некоторые особенности, специфические для ОС Linux.

*/

=========================

/*
* FILE: threading.c
* C Code for pthread_create() test
ЧТОБЫ СКОМПИЛИРОВАТЬ = $ gcc -lpthread 	progname.c ///ЧТОБЫ ПОЛУЧИТЬ ИСПОЛНЯЕМЫЙ ФАЙЛ = $ gcc -lpthread -o	progname.c

*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NTHREADS 1000
void *do_nothing(void *null)
{
	int i;
	i=0;
	pthread_exit(NULL);
}
int main(int argc, char *argv[]) 
{
	int rc, i, j, detachstate;
	pthread_t tid; /*идентификатор нити.*/
	pthread_attr_t attr; /*Thread attributes record*/
	pthread_attr_init(&attr); /* инициализирует объект с атрибутами нити.*/
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); /* Если поток создается неотделенным (PTHREAD_CREATE_JOINABLE), предполагается, что создающий поток будет ожидать его завершения и выполнять в созданном потоке pthread_join().*/
	for (j=0; j<NTHREADS; j++)
 {
		rc = pthread_create(&tid, &attr, do_nothing, NULL); // создаём нить.
		if (rc) {
		printf("ERROR; return code from pthread_create() is %d\n", rc);
		exit(-1);
		}
		/* Wait for the thread */
		rc = pthread_join(tid, NULL); // Функция nt pthread_join (pthread_t thread, void **status_addr); блокирует работу вызвавшей ее нити исполнения до завершения thread'а с идентификатором thread.- то есть мы ждём завершения каждой порождённой нити в главной нити мэйна
		if (rc) {
		printf("ERROR; return code from pthread_join() is %d\n", rc);
		exit(-1);
	}
	}
	pthread_attr_destroy(&attr);
	pthread_exit(NULL);
}


/******************************************************************************
* FILE: hello.c
* DESCRIPTION:
* A "hello world" Pthreads program. Demonstrates thread creation and
* termination.
* AUTHOR: Blaise Barney
* LAST REVISED: 04/05/05
******************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
	int tid;
	tid = (int)threadid;
	printf("Hello World! It's me, thread это нить номер #%d!\n", tid);
	pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
	pthread_t threads[NUM_THREADS];
	int rc, t;
	for(t=0;t<NUM_THREADS;t++)
  {
		printf(" Создаём нить In main: creating thread %d\n", t);
		rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
		if (rc)
    {
			printf("ERROR; return code from pthread_create() is %d\n", rc);
			exit(-1);
	  }
	}
	pthread_exit(NULL);
}

/******************************************************************************
* FILE: hello_arg1.c
* DESCRIPTION:
* A "hello world" Pthreads program which demonstrates one safe way
* to pass arguments to threads during thread creation.
* AUTHOR: Blaise Barney
* LAST REVISED: 04/05/05
******************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 8
char *messages[NUM_THREADS];
void *PrintHello(void *threadid)
{
	int *id_ptr, taskid;
	sleep(1);
	id_ptr = (int *) threadid;
	taskid = *id_ptr;
	printf("Thread %d: %s\n", taskid, messages[taskid]);
	pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
	pthread_t threads[NUM_THREADS];
	int *taskids[NUM_THREADS];
	int rc, t;
	messages[0] = "English: Hello World!";
	messages[1] = "French: Bonjour, le monde!";
	messages[2] = "Spanish: Hola al mundo";
	messages[3] = "Klingon: Nuq neH!";
	messages[4] = "German: Guten Tag, Welt!";
	messages[5] = "Russian: Zdravstvytye, mir!";
	messages[6] = "Japan: Sekai e konnichiwa!";
	messages[7] = "Latin: Orbis, te saluto!";
	for(t=0;t<NUM_THREADS;t++) 
  {
		taskids[t] = (int *) malloc(sizeof(int)); // резервируем область памяти для очередного элемента массива номеров.
		*taskids[t] = t;
		printf("Creating thread %d\n", t);
		rc = pthread_create(&threads[t], NULL, PrintHello, (void *) taskids[t]); // здесь происходит передача параметра после имени функции ,которую будет выполннить.
		if (rc) 
		{
			printf("ERROR; return code from pthread_create() is %d\n", rc);
			exit(-1);
		}
	}
	pthread_exit(NULL);
}

#include <pthread.h>
#include <stdio.h>
#define NTHREADS 4
#define N 1000
#define MEGEXTRA 1000000
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
pthread_attr_t attr;
void *dowork(void *threadid)
{
	double A[N][N];
	int i,j,tid;
	size_t mystacksize;
	tid = (int)threadid;
	pthread_attr_getstacksize (&attr, &mystacksize);
	printf("Thread %d: stack size = %d bytes \n", tid, mystacksize);
	for (i=0; i<N; i++)
	for (j=0; j<N; j++)
	A[i][j] = ((i*j)/3.452) + (N-i);
	pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
	pthread_t threads[NTHREADS];
	size_t stacksize;
	int rc, t;
	pthread_attr_init(&attr);
	pthread_attr_getstacksize (&attr, &stacksize);
	printf("Default stack size = %d\n", (int) stacksize);
	stacksize = sizeof(double)*N*N+MEGEXTRA; // рассчитываем новый размер стека по формуле.
	printf("Amount of stack needed per thread = %d\n",(int)stacksize);
	pthread_attr_setstacksize (&attr, stacksize);
	printf("Creating threads with stack size = %d bytes\n",(int) stacksize);
	for(t=0; t<NTHREADS; t++)
  {
		rc = pthread_create(&threads[t], &attr, dowork, (void *)t); // порождаем нити в цикле.
		if (rc)
		{
			printf("ERROR; return code from pthread_create() is %d\n", rc);
			exit(EXIT_FAILURE);
		}
	}
	printf("Created %d threads.\n", t);
	pthread_exit(NULL);
}

_________ _ _ ______
dthcbz фкн вгу and co

С каждым сокет связываются три атрибута: домен, тип и протокол. Эти атрибуты задаются при создании сокета и остаются неизменными на протяжении всего времени его существования. Для создания сокета используется функция socket, имеющая следующий прототип.

#include <sys/types.h>
#include <sys/socket.h>

int socket(int domain, int type, int protocol);

_________ _ _ ______
dthcbz фкн вгу and co

/*
* getname.c
*/
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
	char *host, **names, **addrs;
	struct hostent *hostinfo;
	/* В качетве параметра передается имя хоста, или используется текущий хост:*/
	if(argc == 1) {
	char myname[256];
	gethostname(myname, 255);
	host = myname;
	}
	else
	host = argv[1];
	hostinfo = gethostbyname(host);
	if(!hostinfo) {
	fprintf(stderr, "cannot get info for host: %s\n", host);
	exit(1);
	}
	printf("results for host %s:\n", host);
	printf("Name: %s\n", hostinfo -> h_name);
	printf("Aliases:");
	names = hostinfo -> h_aliases;
	while(*names) {
	printf(" %s", *names);
	names++;
	}
	printf("\n");

	/* Может быть это не IP хост:*/
	if(hostinfo -> h_addrtype != AF_INET)
	{
		fprintf(stderr, "not an IP host!\n");
		exit(1);
		}
		/* Отобразить? IP адрес:*/
		addrs = hostinfo -> h_addr_list;
		while(*addrs) 
		{
			printf(" %s", inet_ntoa(*(struct in_addr *)*addrs));
			addrs++;
		}
	printf("\n");
	exit(0);
}

_________ _ _ ______
dthcbz фкн вгу and co

/* Создание очереди на соединение и игнорируется состояние потомка:*/
	listen(server_sockfd, 5);
	signal(SIGCHLD, SIG_IGN);
	while(1) 
  {
		char ch;
		printf("server waiting\n");
		/* Принимаем запрос на соединение */
		client_len = sizeof(client_address);
		client_sockfd = accept(server_sockfd,
		(struct sockaddr *)&client_address, &client_len);
		/* порождаем процесс потомок */
		if(fork() == 0) 
		{
			/* Потомок: обслуживаем запросы клиента по сокету client_sockfd с задержкой 5 сек*/
			read(client_sockfd, &ch, 1);
			sleep(5);
			ch++;
			write(client_sockfd, &ch, 1);
			close(client_sockfd);
			exit(0);
		}
		/* Родитель: завершает работу с клиентом */
		else 
		{
			close(client_sockfd);
		}
	}

_________ _ _ ______
dthcbz фкн вгу and co