MyBooks.club
Все категории

Марк Митчелл - Программирование для Linux. Профессиональный подход

На сайте mybooks.club вы можете бесплатно читать книги онлайн без регистрации, включая Марк Митчелл - Программирование для Linux. Профессиональный подход. Жанр: Программирование издательство -,. Доступна полная версия книги с кратким содержанием для предварительного ознакомления, аннотацией (предисловием), рецензиями от других читателей и их экспертным мнением.
Кроме того, на сайте mybooks.club вы найдете множество новинок, которые стоит прочитать.

Название:
Программирование для Linux. Профессиональный подход
Издательство:
-
ISBN:
-
Год:
-
Дата добавления:
17 сентябрь 2019
Количество просмотров:
290
Читать онлайн
Марк Митчелл - Программирование для Linux. Профессиональный подход

Марк Митчелл - Программирование для Linux. Профессиональный подход краткое содержание

Марк Митчелл - Программирование для Linux. Профессиональный подход - описание и краткое содержание, автор Марк Митчелл, читайте бесплатно онлайн на сайте электронной библиотеки mybooks.club
Данная книга в основном посвящена программированию в среде GNU/Linux. Авторы применяют обучающий подход, последовательно излагая самые важные концепции и методики использования расширенных возможностей системы GNU/Linux в прикладных программах. Читатели научатся писать программы, к интерфейсу которых привыкли пользователи Linux; освоят такие технологии, как многозадачность, многопотоковое программирование, межзадачное взаимодействие и взаимодействие с аппаратными устройствами; смогут улучшить свои программы, сделав их быстрее, надежнее и безопаснее; поймут особенности системы GNU/Linux, ее ограничения, дополнительные возможности и специфические соглашения.Книга предназначена для программистов, уже знакомых с языком С и имеющих базовый опыт работы в GNU/Linux.

Программирование для Linux. Профессиональный подход читать онлайн бесплатно

Программирование для Linux. Профессиональный подход - читать книгу онлайн бесплатно, автор Марк Митчелл

#include <string.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <unistd.h>

#include "server.h"


/* HTML-код начала генерируемой страницы. */

static char* page_start =

 "<html>n"

 " <body>n"

 "  <pre>n";


/* HTML-код конца генерируемой страницы. */

static char* page_end =

 "  </pre>n"

 " </body>n"

 "</html>n";


void module_generate(int fd) {

 pid_t child_pid;

 int rval;


 /* Запись начала страницы. */

 write(fd, page_start, strlen(page_start));

 /* Создание дочернего процесса. */

 child_pid = fork();

 if (child_pid == 0) {

  /* Это дочерний процесс. */

  /* Подготовка списка аргументов команды df. */

  char* argv[] = { "/bin/df, "-h", NULL };


  /* Дублирование потоков stdout и stderr для записи данных

     в клиентский сокет. */

  rval = dup2(fd, STDOUT_FILENO);

  if (rval == -1)

   system_error("dup2");

  rval = dup2(fd, STDERR_FILENO);

  if (rval == -1)

   system_error("dup2");

  /* Запуск команды df, отображающей объем свободного

     пространства в смонтированных файловых системах. */

  execv(argv[0], argv);

  /* Функция execv() возвращает управление в программу только

     при возникновении ошибки. */

  system_error("execv");

 } else if (child_pid > 0) {

  /* Это родительский процесс, дожидаемся завершения дочернего

     процесса. */

  rval = waitpid(child_pid, NULL, 0);

  if (rval == -1)

   system_error("waitpid");

 } else

  /* Вызов функции fork() завершился неудачей. */

  system_error("fork");

 /* запись конца страницы. */

 write(fd, page_end, strlen(page_end));

}

В то время как модуль issue.so посылает содержимое файла с помощью функции sendfile(), данный модуль должен вызвать внешнюю команду и перенаправить результаты ее работы клиенту. Для этого модуль придерживается такой последовательности действий.

1. Сначала с помощью функции fork() создается дочерний процесс (см. раздел 3.2.2. "Функции fork() и exec()").

2. Дочерний процесс копирует дескриптор сокета в дескрипторы STDOUT_FILENO и STDERR_FILENO, соответствующие стандартным потокам вывода и ошибок (см. раздел 2.1.4, "Стандартный ввод-вывод"). Это копирование осуществляется с помощью системного вызова dup2() (см. раздел 5.4 3. "Перенаправление стандартных потоков ввода, вывода и ошибок"). Все последующие данные, записываемые в эти потоки в рамках дочернего процесса, будут направляться в сокет.

3. Дочерний процесс с помощью функции execv() вызывает команду df -h.

4. Родительский процесс дожидается завершения дочернего процесса, вызывая функцию waitpid() (см. раздел 5.4 2. "Системные вызовы wait()").

Этот модуль можно легко настроить на вызов другой системной команды.

11.3.4. Статистика выполняющихся процессов

Модуль processes.so (исходный текст приведен в листинге 11.9) сложнее остальных модулей. Он генерирует страницу, в которой содержится таблица процессов, выполняющихся в данный момент на сервере. Каждому процессу отводится в таблице одна строка. В этой строке указан идентификатор процесса, имя исполняемого файла, имена владельца и группы, которым принадлежит процесс, а также размер резидентной части процесса.

Листинг 11.9. (processes.c) Серверный модуль, отображающий таблицу процессов

#include <assert.h>

#include <dirent.h>

#include <fcntl.h>

#include <grp.h>

#include <pwd.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <sys/uio.h>

#include <unistd.h>

#include "server.h"


/* Эта функция записывает в аргументы UID и GID

   идентификаторы пользователя и группы, которым

   принадлежит процесс с указанным идентификатором,

   в случае успешного завершения возвращается нуль,

   иначе -- ненулевое значение. */

static int get_uid_gid(pid_t pid, uid_t* uid, gid_t* gid) {

 char dir_name[64];

 struct stat dir_info;

 int rval;


 /* Формирование имени каталога процесса

    в файловой системе /proc. */

 snprintf(dir_name, sizeof(dir_name), "/proc/%d", (int)pid);


 /* Получение информации о каталоге. */

 rval = stat(dir_name, &dir_info);

 if (rval != 0)

  /* Каталог не найден. Возможно, процесс больше

     не существует. */

  return 1;

 /* Убеждаемся в том, что это действительно каталог. */

 assert(S_ISDIR(dir_info.st_mode));


 /* Определяем интересующие нас идентификаторы. */

 *uid = dir_info.st_uid;

 *gid = dir_info.st_gid;

 return 0;

}


/* Эта функция находит имя пользователя,

   соответствующее заданному идентификатору.

   Возвращаемый буфер должен быть удален

   в вызывающей функции. */

static char* get_user_name(uid_t uid) {

 struct passwd* entry;

 entry = getpwuid(uid);

 if (entry == NULL)

  system_error("getpwuid");

 return xstrdup(entry->pw_name);

}


/* Эта функция находит имя группы, соответствующее

   заданному идентификатору, возвращаемый буфер

   должен быть удален в вызывающей функции. */

static char* get_group_name(gid_t gid) {

 struct group* entry;

 entry = getgrgid(gid);

 if (entry == NULL)

  system_error("getgrgid");

 return xstrdup(entry->gr_name);

}


/* Эта функция находит имя программы, которую выполняет

   процесс с заданным идентификатором. Возвращаемый буфер

   должен быть удален в вызывающей функции. */

static char* get_program_name(pid_t pid) {

 char file_name[64];

 char status_info[256];

 int fd;

 int rval;

 char* open_paren;

 char* close_paren;

 char* result;


 /* Генерируем имя файла "stat", находящегося в каталоге

    данного процесса в файловой системе /proc,

    и открываем этот файл. */

 snprintf(file_name, sizeof(file_name), "/proc/%d/stat",

  (int)pid);

 fd = open(file_name, O_RDONLY);

 if (fd == 1)

  /* Файл не удалось открыть. Возможно, процесс

     больше не существует. */

  return NULL;

 /* Чтение содержимого файла

 rval = read(fd, status_info, sizeof(status_info) — 1);

 close(fd);

 if (rval <= 0)

  /* По какой-то причине файл не удалось прочитать, завершаем

     работу. */

  return NULL;

 /* Завершаем прочитанный текст нулевым символом. */

 status_info[rval] = '';


 /* Имя программы -- это второй элемент файла, заключенный в

    круглые скобки. Находим местоположение скобок. */

 open_paren = strchr(status_info, '(');

 close_paren = strchr(status_info, ')');

 if (open_paren == NULL ||

  close_paren == NULL || close_paren < open_paren)

  /* He удалось найти скобки, завершаем работу. */

  return NULL;

 /* Выделение памяти для результирующей строки */

 result = (char*)xmalloc(close_paren — open_paren);

 /* Копирование имени программы в буфер. */

 strncpy(result, open_paren + 1, close_paren - open_paren — 1);

 /* Функция strncpy() не завершает строку нулевым символом,

    приходится это делать самостоятельно. */

 result[close_paren - open_paren - 1] = '';

 /* Конец работы. */

 return result;

}


/* Эта функция определяет размер (в килобайтах) резидентной

   части процесса с заданным идентификатором.

   В случае ошибки возвращается -1. */

static int get_rss(pid_t pid) {

 char file_name[64];

 int fd;

 char mem_info[128];

 int rval;

 int rss;


 /* Генерируем имя файла "statm", находящегося в каталоге

    данного процесса в файловой системе proc. */

 snprintf(file_name, sizeof(file_name), "/proc/%d/statm",

  (int)pid);

 /* Открытие файла. */

 fd = open(file_name, O_RDONLY);

 if (fd == -1)

  /* Файл не удалось открыть. Возможно, процесс больше не


Марк Митчелл читать все книги автора по порядку

Марк Митчелл - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки mybooks.club.


Программирование для Linux. Профессиональный подход отзывы

Отзывы читателей о книге Программирование для Linux. Профессиональный подход, автор: Марк Митчелл. Читайте комментарии и мнения людей о произведении.

Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*
Все материалы на сайте размещаются его пользователями.
Администратор сайта не несёт ответственности за действия пользователей сайта..
Вы можете направить вашу жалобу на почту librarybook.ru@gmail.com или заполнить форму обратной связи.