Fórum Ubuntu CZ/SK
Ubuntu pro osobní počítače => Software => Příkazový řádek a programování pro GNU/Linux => Téma založeno: mizik 02 Února 2010, 17:24:31
-
Zdravim,
narazil jsem na problem pri pouziti asynchroniho zapisu do souboru(aio_write)
Program vychazi z ukazky na http://docs.hp.com/en/B9106-90009/aio_write.2.html
Nedela nic jineho, nez ze si nazacatku alokuje pole ukazatelu na data (ktera vyplni poradovym cislem) a pote se v cyklu vola aio_write.
Problem je v tom, ze vysleny soubor(test.bin) obsahuje jina data nez se da ocekavat:
ocekavam data
00000000000....000 (32x0)
11111111111....111(32x1)
..
..
128 128 128....128 (32x128)
ale zapisou se mi data:
0000.....0000 ( 1826 x 0 )
58 58 58 ...... (32x58)
0 0 0 0 0....0 (128x0)
78 78 78 ..... ( 32 x 78 )
...
..
..
Cislo 58 je spravne, ale pred nim by melo byt 32x1 .... 32x57
Ciso 78 tez sedi opet ale mezi nim a 58 jsou zahadne 0
#include <fcntl.h>
#include <errno.h>
#include <aio.h>
typedef BYTE unsigned char;
int main()
{
const int a_size = 128;
const int i_size = 32;
BYTE ** buffers = new BYTE* [a_size];
int j = 0l
for( j = 0; j < a_size; j++ )
{
buffers[j] = new BYTE[i_size];
memset( buffers[j], j, i_size ); //pro kontrolu nastavim kazdy buffer na rozlicny obsah
}
int retval;
ssize_t nbytes;
struct aiocb myaiocb;
memset( &myaiocb,0, sizeof (aiocb));
/* nastaveni pevny parametru ktere nebudu menit */
myaiocb.aio_fildes = open( "test.bin", O_RDWR|O_CREAT);
myaiocb.aio_nbytes = i_size;
myaiocb.aio_sigevent.sigev_notify = SIGEV_NONE;
for( j = 0; j < a_size; j++ )
{
myaiocb.aio_buf = (void *) buffers[j];
retval = aio_write( &myaiocb );
myaiocb.aio_offset += i_size; //chci zapsat dal, tak se posunu o to co jsem zapsal
if (retval) perror("aio_write:");
}
printf("waiting\n");
while ( (retval = aio_error( &myaiocb) ) == EINPROGRESS) ;
nbytes = aio_return( &myaiocb);
/*
dealokace pameti ...
*/
return 0;
}
Kdyby nekoho napadly duvody proc zapisu jina data nez mam v umyslu, diky.
(vysledny "spatny" soubor je k prohlednuti na http://mizici.com/test.bin)
-
Tak první věc: když se ti vrátí z toho čekacího cyklu, nekontroluješ návratovou hodnotu aio_error (nemusí být jen EINPROGRESS, může to být kterákoliv jiná chyba). Vypisuje ti to 128x waiting, nebo jen jednou?
Edit: Ještě jsem zapomněl dodat, že to co jsi sem postnul je nepřeložitelné, natožpak aby to fungovalo. Krom špatného pořadí parametrů typedef, chybějícího středníku za deklarací j a chybějících hlavičkových souborů máš ještě posunutou uzavírací závorku for cyklu, která by hádám měla být až za řádkem s aio_return ;)
-
Todle má být jak?
int j = 0l
for( j = 0; j < a_size; j++ )
Takhle:
for(int j = 0; j < a_size; j++ )
???
-
Povedlo se mi to zprovoznit, tady je kód s opravami:
#include <fcntl.h>
#include <errno.h>
#include <aio.h>
#include <stdio.h>
#include <cstring>
typedef unsigned char BYTE;
int main()
{
const int a_size = 128;
const int i_size = 32;
BYTE ** buffers = new BYTE* [a_size];
int j = 0l;
for( j = 0; j < a_size; j++ )
{
buffers[j] = new BYTE[i_size];
memset( buffers[j], j, i_size ); //pro kontrolu nastavim kazdy buffer na rozlicny obsah
}
int retval;
ssize_t nbytes;
struct aiocb myaiocb;
memset( &myaiocb,0, sizeof (aiocb));
/* nastaveni pevny parametru ktere nebudu menit */
myaiocb.aio_fildes = open( "test.bin", O_RDWR|O_CREAT);
myaiocb.aio_nbytes = i_size;
myaiocb.aio_sigevent.sigev_notify = SIGEV_NONE;
for( j = 0; j < a_size; j++ )
{
printf("Writing %d\n", j);
myaiocb.aio_buf = (void *) buffers[j];
retval = aio_write( &myaiocb );
myaiocb.aio_offset += i_size; //chci zapsat dal, tak se posunu o to co jsem zapsal
if (retval) perror("aio_write: ");
printf("waiting\n");
while ( (retval = aio_error( &myaiocb) ) == EINPROGRESS) ;
if (retval != 0) perror("aio_error: ");
nbytes = aio_return( &myaiocb);
}
/*
dealokace pameti ...
*/
return 0;
}
-
Omlouvam se, pri odstranovani "omacky" kolem, jsem zde udelal preklep.
spravne ma byt....
int j = 0;
-
Ono když to int šoupnete rovnou do tý závorky k for, tak ušetříte v kódu jeden řádek ;)
-
Edit: Ještě jsem zapomněl dodat, že to co jsi sem postnul je nepřeložitelné, natožpak aby to fungovalo. Krom špatného pořadí parametrů typedef, chybějícího středníku za deklarací j a chybějících hlavičkových souborů máš ještě posunutou uzavírací závorku for cyklu, která by hádám měla být až za řádkem s aio_return ;)
Omlouvam se, pri zjednodusovani kodu coz jsem delal v editacnim okne, jsem napachal spousty chyb. Sypu si popel na hlavu :-)
Zde je zkompilovatelna verze:
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <aio.h>
#include <string.h>
typedef unsigned char BYTE;
int main()
{
const int a_size = 128;
const int i_size = 32;
BYTE ** buffers = new BYTE* [a_size];
int j = 0;
for( j = 0; j < a_size; j++ )
{
buffers[j] = new BYTE[i_size];
memset( buffers[j], j, i_size ); //pro kontrolu nastavim kazdy buffer na rozlicny obsah
}
int retval;
ssize_t nbytes;
struct aiocb myaiocb;
memset( &myaiocb,0, sizeof (aiocb));
/* nastaveni pevny parametru ktere nebudu menit */
myaiocb.aio_fildes = open( "test.bin", O_RDWR|O_CREAT);
myaiocb.aio_nbytes = i_size;
myaiocb.aio_sigevent.sigev_notify = SIGEV_NONE;
for( j = 0; j < a_size; j++ )
{
myaiocb.aio_buf = (void *) buffers[j];
retval = aio_write( &myaiocb );
myaiocb.aio_offset += i_size; //chci zapsat dal, tak se posunu o to co jsem zapsal
if (retval) perror("aio_write:");
}
printf("waiting\n");
while ( (retval = aio_error( &myaiocb) ) == EINPROGRESS) ;
nbytes = aio_return( &myaiocb);
/*
dealokace pameti ...
*/
return 0;
}
-
Ono když to int šoupnete rovnou do tý závorky k for, tak ušetříte v kódu jeden řádek ;)
jasna vec... ale jelikoz ten int j pouzivam ve vice cyklech, tak mi pripadne opticky hezci si ho deklarovat na zacatku. ::)
-
Tak první věc: když se ti vrátí z toho čekacího cyklu, nekontroluješ návratovou hodnotu aio_error (nemusí být jen EINPROGRESS, může to být kterákoliv jiná chyba).
Nekontroluju, ale predpokladam, ze pokud vysledek bude jiny nez EINPROGRESS (nejaka chyba) tak se mi do souboru nic nezapise. Podle poctu "radku" (tim myslim 32x cislo) ve vyslednem souboru, je videt, ze se vse zapise, ale data ktera tam zapisuju, tak jsou jina nez tam chci dat.
Coz me vrta hlavou, jelikoz si pro kazde volani aio_write alokuju a vyplnim 1 buffer ktery mu predam a pote nikde jinde jiz nepouziji. :(
Vypisuje ti to 128x waiting, nebo jen jednou?
jestli muzes, tak mrkni na ten vyslednej soubor a uvidis...
-
No já koukal na ten výslednej soubor a je to nějaká šílená binárka.
Co přesně má umět ta třída aio ať to nemusím někde sáhodlouze hledat?
PS: není možné, že si tam ta třída připisuje svoje znaky? V MFC třeba CArchive, když ukládá do binárky, tak si taky kolem sebe rozhazuje data ;)
-
No já koukal na ten výslednej soubor a je to nějaká šílená binárka.
Co přesně má umět ta třída aio ať to nemusím někde sáhodlouze hledat?
PS: není možné, že si tam ta třída připisuje svoje znaky? V MFC třeba CArchive, když ukládá do binárky, tak si taky kolem sebe rozhazuje data ;)
Ano, zapisuju tam binarni data (respektive radu 32x cislo, pote by melo nasledovat 32xcislo+1 atd...) Je mozne to predelat klidne na text....
AIO == asynchronous input/output.... spousta omacky je na wiki http://en.wikipedia.org/wiki/Asynchronous_I/O ale je to celkem o nicem...
Spis nez o tridu, se jedna o volne funkce.(glob.), ktere maji za ukol, napr. zapis do souboru. Moje predstava je takova, za data ktera cpu pres ai_write, se ukladaji threadu fronty, kterou pote zpracovava (zapisuje na disk). Narozdil od funcke write je to neblokujici funkce, tj. data predam a vlasni zapis je v threadu....( tim jsem si chtel usetrit praci s vytvorenim vlastniho threadu...)
-
Jestli spuštíš tu zkompilovatelnou variantu, tak bych o jedné chybě věděl. Konec cyklu for máš před čekáním (už jsem to zmiňoval). Nevím jestli si AIO vytváří nějakou frontu, ale vzhledem k tomu, jak se to chová, bych řekl že ne. Takže konec cyklu for dej za řádek nbytes = aio_return( &myaiocb); , aby po každém zápisu čekal na dokončení operace. A doplň si tam tu kontrolu. Mně to třeba vypisuje Permission denied, pokud nesmažu předchozím spuštěním vytvořený soubor (nějaká chybějící práva).
-
Jestli spuštíš tu zkompilovatelnou variantu, tak bych o jedné chybě věděl. Konec cyklu for máš před čekáním (už jsem to zmiňoval). Nevím jestli si AIO vytváří nějakou frontu, ale vzhledem k tomu, jak se to chová, bych řekl že ne. Takže konec cyklu for dej za řádek nbytes = aio_return( &myaiocb); , aby po každém zápisu čekal na dokončení operace. A doplň si tam tu kontrolu.
Jenze pokud to udelam tak jak pises, ztratim preci vyhodu asynchroniho zapisu. Kdyz predam data a pak cekam na jejich zpracovani.... to uz je pak vyhodnejsi pouzit synchroni zapis. Aspon tak to vidim...
Mně to třeba vypisuje Permission denied, pokud nesmažu předchozím spuštěním vytvořený soubor (nějaká chybějící práva).
JJ, prava je treba nastavit pri vytvareni souboru, to jsem nedelal.... staci za open dat do vypustky dalsi flagy napr. S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
-
O výhody nepřicházíš, protože zatímco se provádí asynchronní zápis, ty můžeš dělat něco jiného, a až doděláš to něco jiného, tak si jen vyzvedneš výsledek AIO a zadáš další operaci.
-
O výhody nepřicházíš, protože zatímco se provádí asynchronní zápis, ty můžeš dělat něco jiného, a až doděláš to něco jiného, tak si jen vyzvedneš výsledek AIO a zadáš další operaci.
Jo, to mas pravdu. Jen to pouziti je jine....
u tvoji varianty je 1x aio_write ... pote nejaka dalsi prace .... pote potvrzeni
ja potrebuju: nx aio_write ... pote prace... pote potvrzeni (staci posledni zapis)
a to nxaio_write jsem se pro test snazil nasimulovat v cyklu (for)
At tak ci onak, vysledny soubor obsahuje nuly, ktere by tam podle me nemely byt... pokud aio_write neuspeje, nic se nezapise.... tak proc tam mam nekolikrat tu samou radu cisel? "Zrada" bude podle me nekde jinde....
spis zkusim vyuzit aio_sigevent.sigev_notify handler a mrknout co za data tam davam....
-
AIO == asynchronous input/output ;D ;D ;D dík no.
A není možné, že AIO si to tam přidalo samo?
A co zkusit pthreade + fopen, fwrite, fread ???
-
IMHO ti to frontu požadavků nevytvoří. Pokud to chceš takto, možná bych opravdu šel do těch vláken, fopen, fwrite a fread, a frontu si naimplementoval sám. Nebo tu úlohu přeformulovat tak, aby to použití stačilo. Na co to potřebuješ?
-
eh.. ja se pujdu zahrabat :'( ... ten problem s jinym vysledkem v souboru je zpusoben prenastavovanim hodnot pro jednu instanci strukury.(davam mu 1 instanci aiocb u ktere prenastavuju pointer na data) ...nejak me to nedocvaklo no ::)
Kazdopadne, kdyby jste na to nekdo v budoucnu narazil, je dobre si jeste zaregistrovat call back
myaiocb.aio_sigevent.sigev_notify = SIGEV_THREAD;//SIGEV_CALLBACK
myaiocb.aio_sigevent.sigev_notify_function = aio_completion_handler;//nastavim callback
ktery muze vypadat nasledovne:
void aio_completion_handler( sigval_t sigval )
{
aiocb * req = (struct aiocb *)sigval.sival_ptr;
BYTE * buffers = (BYTE *)req->aio_buf;
//je to ok?
if (aio_error( req ) == 0)
{
//ano mohu kouknout na hodnotu
//ret = aio_return( req );
}
else //nejaka chyba pri zapisu
{
//osetrit
}
}
Diky dadam a Martin - ViPEr*CZ* za pomoc ( +1 )