Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« : 09-08-2004 08:52 » |
|
В связи с организацией доступа и написанного своего шелла для платформы - возникла одна проблемка!
Общение с платформой осуществляется в виде терминального доступа через СОМ порт! В звязи с этим написан шелл - организующий подобную услугу! В него встроена возможность перекачки файлов с хоста на платформу и обратно через YModem протокол!
Данные поступабт через тот же СОМ порт по тому же соединению!
В данный момент столкнулся с проблемкой! Имею написанный код для винды для работы в протоколе! Передача данных организована с помощью Read/WriteFile и управлением таймаутом!
Теперь эти функции прописываются для Линуха на платформе! Задача организовать чтение типа fgetc с возможностью прервать чтение с порта по таймауту!
Вопрос - какие функции это позволяют в Линухе?
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Антон (LogRus)
|
|
« Ответ #1 : 09-08-2004 09:14 » |
|
Гром, для тайм таймаута в простейшем случае используют сигнал SIGALARM/ALARMSIG/ALARM (или как его там) кажется ставишь время таймаута выполняешь чтений если во премя чтения врямя ALARM истекло процесс получит сигнал ALARM который может быть обработан твоим обработчиком. Читать из порта можно как из файла. Управлять портом можно через fcntl (опятьже кажется). С компортом не работал так, что извини. Мне к нему подключать нечего, если тоько консоль дополнительную следелать из него.
|
|
|
Записан
|
Странно всё это....
|
|
|
Антон (LogRus)
|
|
« Ответ #2 : 09-08-2004 09:26 » |
|
|
|
|
Записан
|
Странно всё это....
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #3 : 09-08-2004 09:48 » |
|
LogRus, Я посмотрю - но проблема в том, что я должен все в одном потоке сделать - и чтение типа freadc не имеет параметра АЛАРМ - которое я мог бы выставить!
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #5 : 09-08-2004 10:40 » |
|
А как я получив сигнал выбъю freadc с блокируемого чтения!
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Антон (LogRus)
|
|
« Ответ #6 : 09-08-2004 11:01 » |
|
Гром, его самого должно выкинуть независимо от твоих пожеланий. обработчик только свой установи на сигнал. Он может ничего не делать, что делает стандартный обработчик я не помню.
|
|
|
Записан
|
Странно всё это....
|
|
|
RXL
|
|
« Ответ #7 : 09-08-2004 12:09 » |
|
Стандартный обработчик сигнала завершает программу. Примерчик работы: void my_sig_proc(int sig) { return; }
signal(SIGALRM,my_sig_proc); .......
alarm(1); // устанавливаем таймер на 1 секунду res=read(fd,buf,len); if(res==-1 && errno==EINTR) { // значит операция прервана сигналом } else { alarm(0); // отключаем таймер }
Более точный таймаут можно организовать с помощью select(). Точность, теоретически, до микросекунд, а практически - зависит от ОС. select() можно использовать и с stream ф-ми: int fileno(FILE * STREAM).
|
|
« Последнее редактирование: 30-11-2007 21:58 от Алексей1153++ »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #8 : 09-08-2004 12:22 » |
|
Ага - если я правильно понял - после выполнения сигнала АЛАРМ - заканчивается не программа - как пишет RXL, а все ж таки функция типа колбэк! Я поясню свою задачу - так как несколько запутался!!! Есть int Read(char * buf, int len, ...) { int i; unsigned char ch; for (i=0; i< len; i++) { ch = fgetc(stdin); if (ch) buf[i] = ch; else { if (ERROR) return false; else return true; }
} return true; }
Вот такая примерно в первом приближении функция чтения буфера! Т.е. я читаю буфер и проверяю - если не пришел просто байт то выхожу нормально - если в связи с какой - то ошибкой то выхожу как с ошибкой чтения! В момент чтения - после того как стало ясно что символ не пришел - прошел таймаут, я должен выйти из fgetc() и из процедуры! В вашем варианте вы бинарно читаете - а мне это не надо - во вторых у вас как я уже писал есть некий колбек - мне такого желательно не иметь - надо вылетать из чтения при истечении таймаута! Т.е. нужен полный аналог неблокирумого ReadFile из винды!
|
|
« Последнее редактирование: 30-11-2007 21:59 от Алексей1153++ »
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
Антон (LogRus)
|
|
« Ответ #9 : 09-08-2004 13:21 » |
|
Гром, ну ты прямо Громазека! Такие вопросы. Ваще это довольно стандартная практика сигналами прерывать чтение/запись. alarm(secs); // или ualarm(msecs); ch = fgetc(stdin); // тут проверь ошибки на предмет E_AGAIN. Типа там пусто повторить бы. alarm(0); // кажется так отменяется alarm if (ch) buf[i] = ch; else { if (ERROR) return false; else return true; }
тут смотри: http://www.opennet.ru/docs/RUS/glibc/glibc-8.htmlпро O_NONBLOCK можно выставлять до открытия и после функция fcntl там же еще есть что возможно тебе подойдет. и еще всётаки глянь книжку ссылку на которую я тебе дал я еще читал(изданную прада) очень понравилась. Как говорится читайте маны там много не тривиального.
|
|
« Последнее редактирование: 30-11-2007 22:01 от Алексей1153++ »
|
Записан
|
Странно всё это....
|
|
|
Anonymous
Гость
|
|
« Ответ #10 : 09-08-2004 13:47 » |
|
Ага - если я правильно понял - после выполнения сигнала АЛАРМ - заканчивается не программа - как пишет RXL, а все ж таки функция типа колбэк! Я же говорю - стандартный обработчик сигнала ( signal(SIGимя,SIG_DFL); ). The default behavior for these signals is to cause program termination.Поставив свой обработчик, ты сможешь сам решать, продолжать или закрывать программу. int my_sig_proc(int sig) { exit(0); } // программа завершится int my_sig_proc(int sig) { return; } // выполнение продолжится #include <stdio.h>
void my_sig_proc(int sig) { return; }
... signal(SIGALRM,my_sig_proc); ...
int Read(char * buf, int len, ...) { int i; unsigned char ch; for (i=0; i< len; i++) { alarm(1); ch = fgetc(stdin); alarm(0); if (ch!=EOF) buf[i] = ch; // рекомендую проверку на EOF, а не на 0. Тем более, что EOF!=0 else { if (ferror(stdin)!=EINTR) return false; // другая ошибка else return true; // был таймаут }
} return true; }
|
|
« Последнее редактирование: 30-11-2007 22:03 от Алексей1153++ »
|
Записан
|
|
|
|
Anonymous
Гость
|
|
« Ответ #11 : 09-08-2004 13:49 » |
|
LogRus, неблокируемые терминалы не рекомендую - бывают плавающие глюки с потерей данных.
|
|
|
Записан
|
|
|
|
Антон (LogRus)
|
|
« Ответ #12 : 09-08-2004 13:53 » |
|
Ну я не пробовал. Гром просил не блокирующий.
|
|
|
Записан
|
Странно всё это....
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #13 : 09-08-2004 14:20 » |
|
Видимо терминология опять хромает - я просил организовать не блокируемый - но с помощью своей проверки - т.е. я читаю - только я - но не блокирую на всегда - а блокирую на время - по указанию тайм - аута!
Гость (RXL) Спасибо - я понял - буду пробовать!
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #14 : 10-08-2004 05:54 » |
|
еще можно почитать Serial Programming Guide for POSIX Operating Systems, там все подробно описано, заодно там сказано, как устанавливать тайм-аут на прием байта (на промежуток между байтами). почитайте man tcgetattr()/tcsetattr().
|
|
|
Записан
|
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #15 : 11-08-2004 12:42 » |
|
#include <stdio.h> #include "ymodem.h" #include <unistd.h>
// globals int count_pack=0;
int PackErrorCode=SUCCESS; int Timeout=0; // in seconds
void sig_proc(int sig)|return;}
void SetPortTimeouts(int timeout) { Timeout = timeout; }
bool WriteFile(unsigned char * buf, unsigned int to_write, unsigned int * trans_bytes, void * reserved) { int i; unsigned char ch; if (buf == NULL) return false; if (to_write <=0) return false;
for (i=0; i<to_write; i++) { fputc(ch,stdin); } *trans_bytes = i; return true; }
bool ReadFile(unsigned char * buf, unsigned int to_read, unsigned int * trans_bytes, void * reserved) { int i; unsigned char ch; signal(SIGALRM,sig_proc);
if (buf == NULL) return false; if (to_read == 0) return false; for (i=0; i<to_read; i++) { alarm(1); ch = fgetc(stdin); alarm(0); if (ch!=EOF) buf[i] =ch; else { if (ferror(stdin)) return false; else return true; } } *trans_bytes = i; return true; }
На этот код выдается ошибка в компилляции ymodem.c: In function `ReadFile': ymodem.c:49: `SIGALRM' undeclared (first use in this function) ymodem.c:49: (Each undeclared identifier is reported only once ymodem.c:49: for each function it appears in.) ymodem.c:58: warning: comparison is always true due to limited range of data type Короче говоря - не компилируется SIGALRM - не понимает что это такое - при абстрактном добавлении #define SIGALRM 10 Выбрасывает из программы! Совсем!!! Какие файлы надо подгрузить кроме #include <unistd.h> дабы это заработало?
|
|
« Последнее редактирование: 30-11-2007 22:05 от Алексей1153++ »
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
MOPO3
Ай да дэдушка! Вах...
Команда клуба
Offline
Пол:
Холадна аднака!
|
|
« Ответ #16 : 11-08-2004 13:17 » |
|
|
|
|
Записан
|
MCP, MCAD, MCTS:Win, MCTS:Web
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #17 : 11-08-2004 13:35 » |
|
Откомпилировал - не работает - почему то все равно не выходит из заблокированного fgetc(stdin) помогите что я не так делаю!!!!
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
RXL
|
|
« Ответ #18 : 11-08-2004 19:33 » |
|
Гром, возможно что ф-ия fgetc() обрабатывает ошибки и возобновляет выполнение read() при EINTR. Замени fgetc(stdin) на read(0,buf,1). Завтра проверю что к чему и уточню. Кстати, какая ОС?
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
RXL
|
|
« Ответ #19 : 11-08-2004 20:17 » |
|
А посмотри info libc в разделах "Low-Level Terminal Interface/Terminal Modes/Noncanonical Input" и "Low-Level Terminal Interface/Noncanon Example". Вот мой вариант инициализации порта: #include <termios.h>
char *tty_name="/dev/ttyS0"; char tty_bits[4]="8N1"; char tty_fctrl[2]="N"; int tty=0,tty_speed=19200;
int setup(void) { static struct termios tios;
tty=open(tty_name,O_NOCTTY|O_RDONLY); // !!! read only mode if(tty<0) return 0x40; if(!isatty(tty)) return 0x50;
tcgetattr(tty,&tios); tios.c_iflag=IGNBRK; tios.c_oflag=0; tios.c_lflag=0; tios.c_cc[VMIN]=1; tios.c_cc[VTIME]=0; /* <<< тут-то и надо поставить таймаут в 0.1сек интервалах */ tios.c_cflag=CLOCAL|CREAD; switch(tty_bits[0]) { case '7': tios.c_cflag|=CS7; break; case '8': tios.c_cflag|=CS8; break; default: return 0xa0; } switch(tty_bits[1]) { case 'N': break; case 'E': tios.c_cflag|=PARENB; break; case 'O': tios.c_cflag|=PARENB|PARODD; break; default: return 0xa0; } switch(tty_bits[2]) { case '1': break; case '2': tios.c_cflag|=CSTOPB; break; default: return 0xa0; } switch(tty_fctrl[0]) { case 'N': break; case 'S': tios.c_cflag|=IXON|IXOFF; tios.c_cc[VSTOP]=0x13; tios.c_cc[VSTART]=0x11; break; case 'H': tios.c_cflag|=CRTSCTS; break; default: return 0xa0; } cfsetspeed(&tios,tty_speed); tcsetattr(tty,TCSANOW,&tios); return 0; }
|
|
« Последнее редактирование: 30-11-2007 22:06 от Алексей1153++ »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #20 : 11-08-2004 20:26 » |
|
RXL, не тут я же писал подробно. У меня нет инициализации порта - это делает ОС - я сижу на stdin - СОМ - порте - т.е. роль клаиватурного воода выполняет сериальная коннекция...
ОС eCos - Эмбедед Линукс! Я считываю с терминала который на PC по СОМ порту комманды в программе shell и надо ее же перевести на работу в режиме протокола а потом назад! Вот такая вот фигня - но я поробую вытащить из этого что-нибудь!
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
RXL
|
|
« Ответ #21 : 11-08-2004 20:48 » |
|
Гром, можно сохранить состояние терминала (tcgetattr(tty,&tios) , а потом востановить его. В твоем случае просто не надо менять физичексие параметры, а просто перевести в другой режим работы. Вот страничка с примером (Low-Level Terminal Interface/Noncanon Example): Noncanonical Mode Example =========================
Here is an example program that shows how you can set up a terminal device to read single characters in noncanonical input mode, without echo.
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <termios.h>
/* Use this variable to remember original terminal attributes. */
struct termios saved_attributes;
void reset_input_mode (void) { tcsetattr (STDIN_FILENO, TCSANOW, &saved_attributes); }
void set_input_mode (void) { struct termios tattr; char *name;
/* Make sure stdin is a terminal. */ if (!isatty (STDIN_FILENO)) { fprintf (stderr, "Not a terminal.\n"); exit (EXIT_FAILURE); }
/* Save the terminal attributes so we can restore them later. */ tcgetattr (STDIN_FILENO, &saved_attributes); atexit (reset_input_mode);
/* Set the funny terminal modes. */ tcgetattr (STDIN_FILENO, &tattr); tattr.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */ tattr.c_cc[VMIN] = 1; tattr.c_cc[VTIME] = 0; tcsetattr (STDIN_FILENO, TCSAFLUSH, &tattr); }
int main (void) { char c;
set_input_mode ();
while (1) { read (STDIN_FILENO, &c, 1); if (c == '\004') /* `C-d' */ break; else putchar (c); }
return EXIT_SUCCESS; }
This program is careful to restore the original terminal modes before exiting or terminating with a signal. It uses the `atexit' function (*note Cleanups on Exit::) to make sure this is done by `exit'.
The shell is supposed to take care of resetting the terminal modes when a process is stopped or continued; see *Note Job Control::. But some existing shells do not actually do this, so you may wish to establish handlers for job control signals that reset terminal modes. The above example does so.
Как я понимаю, твой девайс после некой команды, полученной с терминала, переходит в режим приема-передачи файла? Тогда без перенастройки не обойдешься.
|
|
« Последнее редактирование: 30-11-2007 22:08 от Алексей1153++ »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #22 : 12-08-2004 08:44 » |
|
Да именно так и происходит ия должен его настроить - вот теперь понятно в какую сторону копать!!! А то я программирую как-то криво - в чистом С и по привычке с устройствами как с видндовыми общаюсь - психология штука тонкая
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
RXL
|
|
« Ответ #23 : 12-08-2004 08:52 » |
|
Гром, кстати - для Linux-а есть готовые утилиты работы с X/Y/Z-Modem - можеть это будет проще?
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #24 : 12-08-2004 09:00 » |
|
RXL, не там специфично все - Файловая система jffs все равно все перелопачивать пришлось бы - так что... Да и я все уже написал
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
RXL
|
|
« Ответ #25 : 12-08-2004 10:10 » |
|
Гром, молодец. А при чем тут fs? Речь то о утилите.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #26 : 15-08-2004 08:26 » |
|
RXL, ну возможно я и приурасил файловая там действительно не причем - но не важно. Важно то, что не смотря на то, что заработал alarm и сигнал я получаю в sig_proc выхода из процедуры fgetcc() или read() не происходит - т.е. я оказываюсь вв ситуации когда сигнал могу обработать - но выбить из читения у меня не получается
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
darkelf
Молодой специалист
Offline
|
|
« Ответ #27 : 15-08-2004 12:02 » |
|
По-моему необходимо запретить перезапускать системные вызовы функцией siginterrupt().
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #28 : 15-08-2004 19:28 » |
|
Подробно, что и как: info libc - раздел "Signal Handling/Primitives Interrupted by Signals" Оттуда: If you define `_BSD_SOURCE' or `_GNU_SOURCE' before calling `signal', the default is to resume primitives; otherwise, the default is to make them fail with `EINTR'.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии
Offline
Пол:
Бодрый птах
|
|
« Ответ #29 : 15-08-2004 21:32 » |
|
RXL, хм... что -то туманно пока... надо проспаться
|
|
|
Записан
|
А птичку нашу прошу не обижать!!!
|
|
|
|