Portál AbcLinuxu, 23. dubna 2024 22:15


Dotaz: write() zpusobi stale vyvolavani SIGIO

22.10.2011 01:20 atmel8051
write() zpusobi stale vyvolavani SIGIO
Přečteno: 147×
Odpovědět | Admin
Zdravim, pisu program kterej komunikuje po seriove lince. Prijem dat funguje korektne, ovsem pri zapisu - write() dojde k preruseni SIGIO,ktere se opakuje stale dokola. Potrebuji vsak aby k preruseni programu doslo pouze pri prichodu dat. Je to muj prvni program kde vyuzivam signalu a nevim jak na to. Za kazdou radu budu moc rad.

kousek kodu:
//otevreni seriaku
    fd=open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NONBLOCK); //zajisteni spojeni mezi soub.deskript. a komun. portem
    if(fd<0){
        printf("\033[38mProblem pri otevirani serioveho portu.\033[0m\n\n");
        perror("/dev/ttyUSB0");
        return(1);
    }
    printf("\033[32mSeriovy port otevren v poradku.\033[0m\n");

    saio.sa_handler = funkce_pri_preruseni;
    sigemptyset(&saio.sa_mask);
    saio.sa_flags = 0;
    saio.sa_restorer = NULL;
    sigaction(SIGIO,&saio,NULL);                

    //povolit procesu prijmout SIGIO
    fcntl(fd, F_SETOWN, getpid());
    fcntl(fd, F_SETFL,O_NONBLOCK |  FASYNC); /

    tcgetattr(fd,&oldtio); //zaloha puvodniho nastaveni portu
    //nastaveni portu - Canonnical Input - radek ukoncen znakem ASCII LF
    newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
    newtio.c_iflag = IGNPAR | ICRNL;
    newtio.c_oflag = 0;
//    newtio.c_lflag = ICANON;
    newtio.c_cc[VMIN]=1;
    newtio.c_cc[VTIME]=0;
    tcflush(fd, TCIFLUSH);
    tcsetattr(fd,TCSANOW,&newtio);

    write(fd,.....
Nástroje: Začni sledovat (0) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

Bluebear avatar 22.10.2011 12:22 Bluebear | skóre: 30 | blog: Bluebearův samožerblog | Praha
Rozbalit Rozbalit vše Re: write() zpusobi stale vyvolavani SIGIO
Odpovědět | | Sbalit | Link | Blokovat | Admin
Myslím, že problém je tady:

fcntl(fd, F_SETFL,O_NONBLOCK | FASYNC);

Nastavením O_ASYNC žádáš, aby jádro poslalo SIGIO pokaždé, když je deskriptor připraven přijímat nebo dodat data; drtivou většinu SIGIO dostáváš proto, že deskriptor hlásí připravenost k přijetí dalších dat.

Jiná otázka je, co s tím :-) Bohužel nevím o tom, že by šlo nastavit přijetí signálu jen při přijetí nových dat. Zdá se mi, že ti nezbyde buď při každém SIGIO ověřit stav deskriptoru a zjistit, která z těch situací nastala (select(), poll() nebo něco podobného), nebo, podle aplikace, nechat signály koňovi a používat místo nich select() nebo poll() rovnou.

(Upozorňuji, že jsem odpůrce konceptu signálů, které jsou podle mne užitečné jen pro hlášení kritických situací, takže můj pohled je poněkud ovlivněn. :-) )
To mi připomíná, jak jsem si pořídil květináč, že v něm budu mít květinu. Opravdu tam byla, ale potom být přestala...
Josef Kufner avatar 22.10.2011 14:41 Josef Kufner | skóre: 70
Rozbalit Rozbalit vše Re: write() zpusobi stale vyvolavani SIGIO
Jo, taky bych to viděl spíš na použití select(). Ono tím, že vše béží v jedné smyčce a nikam se z ní neutíká, je vše takové přehlednější a líp se to ladí.
Hello world ! Segmentation fault (core dumped)

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.