Майкл Джонсон - Разработка приложений в среде Linux. Второе издание
- Название:Разработка приложений в среде Linux. Второе издание
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2007
- Город:Москва
- ISBN:978-5-8459-1143-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Майкл Джонсон - Разработка приложений в среде Linux. Второе издание краткое содержание
Книга известных профессионалов в области разработки коммерческих приложений в Linux представляет собой отличный справочник для широкого круга программистов в Linux, а также тех разработчиков на языке С, которые перешли в среду Linux из других операционных систем. Подробно рассматриваются концепции, лежащие в основе процесса создания системных приложений, а также разнообразные доступные инструменты и библиотеки. Среди рассматриваемых в книге вопросов можно выделить анализ особенностей применения лицензий GNU, использование свободно распространяемых компиляторов и библиотек, системное программирование для Linux, а также написание и отладка собственных переносимых библиотек. Изобилие хорошо документированных примеров кода помогает лучше усвоить особенности программирования в Linux.
Книга рассчитана на разработчиков разной квалификации, а также может быть полезна для студентов и преподавателей соответствующих специальностей.
Разработка приложений в среде Linux. Второе издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
170: }
171:
172: pf = open(portname, O_RDWR);
173: if (pf < 0) {
174: poptPrintUsage(optCon, stderr, 0);
175: die(1, strerror(errno), portname);
176: }
177: poptFreeContext(optCon);
178:
179: /* изменить конфигурацию порта */
180: tcgetattr(pf, &pts);
181: pots = pts;
182: /* некоторые настройки устанавливаются произвольно */
183: pts.c_lflag &= ~ICANON;
184: pts.c_lflag &= ~(ECHO | ECHOCTL | ECHONL);
185: pts.c_cflag |= HUPCL;
186: pts.c_cc[VMIN] = 1;
187: pts.c_cc[VTIME] = 0;
188:
189: /* Стандартная обработка CR/LF: это неинтеллектуальный терминал.
190: * Не транслируется:
191: * нет NL -> отображение CR/NL в выводе,
192: * нет CR -> отображение NL во вводе.
193: */
194: pts.c_oflag &= ~ONLCR;
195: pts.c_iflag &= ~ICRNL;
196:
197: /* Теперь перейти на сторону локального терминала */
198: tcgetattr(STDIN_FILENO, &sts);
199: sots = sts;
200: /* и снова несколько произвольных настроек */
201: sts.c_iflag &= ~(BRKINT | ICRNL);
202: sts.c_iflag |= IGNBRK;
203: sts.c_lflag &= ~ISIG;
204: sts.c_cc[VMIN] = 1;
205: sts.c_cc[VTIME] = 0;
206: sts.c_lflag &= ~ICANON;
207: /* нет локального эхо: разрешить эхо-контроль на другом конце */
208: sts.c_lflag &= ~(ECHO | ECHOCTL | ECHONL);
209:
210: /* обработка опций сейчас будет модифицировать pts и sts */
211: switch (flow) {
212: case 'h' :
213: /* аппаратное управление потоком */
214: pts.c_cflag |= CRTSCTS;
215: pts.c_iflag &= ~(IXON | IXOFF | IXANY);
216: break;
217: case 's':
218: /* программное управление потоком */
219: pts.c_cflag &= ~CRTSCTS;
220: pts.c_iflag |= IXON | IXOFF | IXANY;
221: break;
222: case 'n':
223: /* отключение управления потоком */
224: pts.c_cflag &= ~CRTSCTS;
225: pts.c_iflag &= ~(IXON | IXOFF | IXANY);
226: break;
227: }
228: if (crnl) {
229: /* послать CR с NL */
230: pts.c_oflag |= ONLCR;
231: }
232:
233: /* скорость не изменяется, пока не будет указано -b */
234: if (speed) {
235: cfsetospeed(&pts, symbolic_speed(speed));
236: cfsetispeed(&pts, symbolic_speed(speed));
237: }
238:
239: /* установить обработчик сигналов для восстановления
240: * старого обработчика termios */
241: sact.sa_handler = cleanup_termios;
242: sigaction(SIGHUP, &sact, NULL);
243: sigaction(SIGINT, &sact, NULL);
244: sigaction(SIGPIPE, &sact, NULL);
245: sigaction(SIGTERM, &sact, NULL);
246:
247: /* установить измененные настройки termios */
248: tcsetattr(pf, TCSANOW, &pts);
249: tcsetattr(STDIN_FILENO, TCSANOW, &sts);
250:
251: ufds[0].fd = STDIN_FILENO;
252: ufds[0].events = POLLIN;
253: ufds[1].fd = pf;
254: ufds[1].events = POLLIN;
255:
256: do {
257: int r;
258:
259: r = poll(ufds, 2, -1);
260: if ((r < 0) && (errno != EINTR))
261: die(1, "неожиданный сбой poll", "");
262:
263: /* сначала проверить возможность завершения */
264: if ((ufds[0].revents | ufds[1].revents) &
265: (POLLERR | POLLHUP | POLLNVAL)) {
266: done = 1;
267: break;
268: }
269:
270: if (ufds[1].revents & POLLIN) {
271: /* pf содержит символы */
272: i = read (pf, buf, BUFSIZE);
273: if (i >= 1) {
274: write(STDOUT_FILENO, buf, i);
275: } else {
276: done = 1;
277: }
278: }
279: if (ufds[0].revents & POLLIN) {
280: /* стандартный ввод содержит символы */
281: i = read(STDIN_FILENO, buf, BUFSIZE);
282: if (i >= 1) {
283: if (raw) {
284: write(pf, buf, i);
285: } else {
286: cook_buf(pf, buf, i);
287: }
288: } else {
289: done = 1;
290: }
291: }
292: } while (!done);
293:
294: /* восстановить первоначальные настройки терминала и завершиться*/
295: tcsetattr(pf, TCSANOW, &pots);
296: tcsetattr(STDIN_FILENO, TCSANOW, &sots);
297: exit(0);
298: }
Код robin.с
начинается с включения нескольких заголовочных файлов (почитайте man-страницы для каждого системного вызова и библиотечной функции, чтобы узнать, какие файлы включать), а затем в нем определяются несколько полезных функций.
Функция symbolic_speed()
в строке 19 преобразует целочисленную скорость в символическую, которую поддерживает termios
. К сожалению, termios не предназначен для работы с произвольными скоростями, так что каждая скорость, которую вы хотите использовать, должна быть частью интерфейса пользователь — ядро [110] На man-странице setserial описан способ обхода этого ограничения, специфический для Linux.
.
Обратите внимание, что предусмотрены и довольно высокие скорости. Не все последовательные порты поддерживают скорости 230 400 или 460 800 бит/с; в стандарте POSIX определены скорости лишь до 38 400 бит/с. Чтобы сделать эту программу переносимой, каждую строку над строкой, в которой устанавливается скорость 38 400 бит/с, потребуется расширить до трех строк, как показано ниже:
#ifdef В460800
if (speednum >= 460800) return B46000;
#end if
Это позволит пользователям устанавливать скорости выше тех, которые последовательные порты способны поддерживать, а исходный код теперь будет компилироваться в любой системе с POSIX termios
. (Как упоминалось ранее в этой главе, любой последовательный порт может отказаться принять на обработку любую установку termios
, которую он не способен поддержать, включая также установки скорости. Поэтому установка B460800
не означает, что можно установить скорость порта равной 460 800 бит/с.)
В строках 44—55 определяются глобальные переменные для передачи некоторых переменных обработчику сигналов и сам обработчик сигналов. Обработчик сигналов предназначен для восстановления настроек termios на обоих интерфейсах tty при доставке сигнала, поэтому ему необходимо получить доступ к структурам, содержащим старые настройки termios
. Ему также необходимо знать файловый дескриптор или последовательный порт (файловый дескриптор для стандартных входных данных не меняется, поэтому компилируется в бинарный). Этот код идентичен коду в случае нормального пути завершения, который рассматривается позже. Обработчик сигналов затем прикрепляется к сигналам, которые завершат процесс, если они были проигнорированы.
Функции send_escape()
и cook_buf()
будут рассматриваться позже. Они используются как часть обработки входных данных в цикле ввода-вывода в конце функции main()
.
Условно скомпилированный sleep(600)
в начале функции main()
предназначен для отладки. С целью отладки программ, модифицирующих настройки termios
для стандартных входных или выходных данных, лучше всего присоединить процесс в другой окне или терминальном сеансе. Однако это означает, что нельзя установить точку прерывания на основную функцию и проходить по одной инструкции за раз. Необходимо запустить программу, найти идентификатор ее процесса и присоединиться к ней из отладчика. Более подробно этот процесс описан далее в настоящей главе.
Интервал:
Закладка: