Нейл Мэтью - Основы программирования в Linux
- Название:Основы программирования в Linux
- Автор:
- Жанр:
- Издательство:«БХВ-Петербург»
- Год:2009
- Город:Санкт-Петербург
- ISBN:978-5-9775-0289-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Нейл Мэтью - Основы программирования в Linux краткое содержание
В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стандартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым.
Для начинающих Linux-программистов
Основы программирования в Linux - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
int main(int argc, char *argv[]) {
struct sigaction new_action, old_action;
message_db_t mess command;
int database_init_type = 0;
new_action.sa_handler = catch_signals;
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
if ((sigaction(SIGINT, &new_action, &old_action) != 0) ||
(sigaction(SIGHUP, &new_action, &old_action) != 0) ||
(sigaction(SIGTERM, &new_action, &old_action) != 0)) {
fprintf(stderr, "Server startup error, signal catching failed\n");
exit(EXIT_FAILURE);
}
if (argc > 1) {
argv++;
if (strncmp("-i", *argv, 2) == 0) database_init_type = 1;
}
if (!database_initialize(database_init_type)) {
fprintf(stderr, "Server error :-\
could not initialize database\n");
exit (EXIT_FAILURE);
}
if (!server starting()) exit(EXIT_FAILURE);
while(server_running) {
if (read_request_from_client(&mess_command)) {
process_command(mess_command);
} else {
if (server_running) fprintf(stderr,
"Server ended — can not read pipe\n");
server_running = 0;
}
} /* while */
server_ending();
exit(EXIT_SUCCESS);
}
3. Любые сообщения клиентов направляются в функцию process_command
, где они обрабатываются в операторе case
, который выполняет соответствующие вызовы из файла cd_dbm.c.
static void process_command(const message_db_t comm) {
message_db_t resp;
int first_time = 1;
resp = comm; /* копирует команду обратно,
затем изменяет resp, как требовалось */
if (!start_resp_to_client(resp)) {
fprintf(stderr, "Server Warning:
start_resp_to_client %d failed\n", resp.client_pid);
return;
}
resp.response = r_success;
memset(resp.error_text, '\0', sizeof(resp.error_text));
save_errno = 0;
switch(resp.request) {
case s_create_new_database:
if (!database initialize(1))
resp.response = r_failure;
break;
case s_get_cdc_entry:
resp.cdc_entry_data =
get_cdc_entry(comm.cdc_entry_data.catalog);
break;
case s_get_cdt_entry:
resp.cdt_entry_data =
get_cdt_entry(comm.cdt_entry_data.catalog,
comm.cdt_entry_data.track_no);
break;
case s_add_cdc_entry:
if (!add_cdc_entry(comm.cdc_entry_data))
resp.response = r_failure;
break;
case s_add_cdt_entry:
if (!add_cdt_entry(comm.cdt_entry_data))
resp.response = r_failure;
break;
case s_del_cdc_entry:
if (!del_cdc_entry(comm.cdc_entry_data.catalog))
resp.response = r_failure;
break;
case s_del_cdt_entry:
if (!del_cdt_entry(comm.cdt_entry_data.catalog,
comm.cdt_entry_data.track_no)) resp.response = r_failure;
break;
case s_find_cdc_entry:
do {
resp.cdc_entry_data =
search_cdc_entry(comm.cdc_entry_data.catalog, &first_time);
if (resp.cdc_entry_data.catalog[0] != 0) {
resp.response = r_success;
if (!send_resp_to_client(resp)) {
fprintf(stderr,
"Server Warning:- failed to respond to %d\n", resp.client_pid);
break;
}
} else {
resp.response = r_find_no_more;
}
} while (resp.response == r_success);
break;
default:
resp.response = r_failure;
break;
} /* switch */
sprintf(resp.error_text,
"Command failed:\n\t%s\n", strerror(save_errno));
if (!send_resp_to_client(resp)) {
fprintf(stderr,
"Server Warning:- failed to respond to %d\n", resp.client_pid);
}
end_resp_to_client();
return;
}
Прежде чем рассматривать действующую реализацию канала, давайте обсудим последовательность событий, которые должны произойти для передачи данных между клиентским и серверным процессами. На рис. 13.9 показан запуск обоих, и клиентского, и серверного, процессов, а также то, как они образуют петлю во время обработки команд и ответов.
В этой реализации ситуация немного сложнее, т.к. в запросе на поиск клиент передает серверу одну команду и затем ждет один или несколько ответов от сервера. Это усложняет программу, особенно клиентскую часть.

Рис. 13.9
Канал
Далее показан файл реализации канала pipe_imp.с, в котором содержатся клиентские и серверные функции.
Как вы видели в главе 10, может быть определено символическое имя DEBUG_TRACE для того, чтобы показать последовательность вызовов, в которых клиентский и серверный процессы передают друг другу сообщения.
1. Прежде всего, директивы #include
:
#include "cd_data.h"
#include "cliserv.h"
2. Вы также определяете в файле программы несколько значений, нужных вам в разных функциях:
static int server_fd = -1;
static pid_t mypid = 0;
static char client_pipe_name[PATH_MAX + 1] = {'\0'};
static int client_fd = -1;
static int client_write_fd = -1;
Далее нужно рассмотреть функции серверной стороны. В следующем разделе показаны функции, открывающие и закрывающие именованный канал и читающие сообщения от клиентов. В следующем за ним разделе приведен программный код, который открывает и закрывает клиентские каналы и пересылает по ним сообщения, основываясь на идентификаторе процесса, который клиент включает в свое сообщение.
1. Подпрограмма server_starting
создает именованный канал, из которого сервер будет считывать команды. Далее она открывает канал для чтения. Этот вызов open
будет блокировать выполнение, пока клиент не откроет канал для записи. Используйте режим блокировки для того, чтобы сервер мог выполнить блокировку вызовов read
в канале в ожидании отправляемых ему команд.
int server_starting(void) {
#if DEBUG_TRACE
printf("%d server_starting()\n", getpid());
#endif
unlink(SERVER_PIPE);
if (mkfifo(SERVER_PIPE, 0777) == -1) {
fprintf(stderr, "Server startup error, no FIFO created\n");
return(0);
}
if ((server_fd = open(SERVER_PIPE, O_RDONLY)) == -1) {
if (errno == EINTR) return(0);
fprintf(stderr, "Server startup error, no FIFO opened\n");
return(0);
}
return(1);
}
2. Когда сервер завершает работу, он удаляет именованный канал, для того чтобы клиенты могли установить, что нет действующего сервера.
Читать дальшеИнтервал:
Закладка: