Prosíme přihlašte se nebo zaregistrujte.

Přihlašte se svým uživatelským jménem a heslem.

Autor Téma: aio [vyřešeno]  (Přečteno 2717 krát)

mizik

  • Návštěvník
  • *
  • Příspěvků: 72
    • Zobrazit profil
    • mizici.com
aio [vyřešeno]
« kdy: 02 Únor 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



Kód: [Vybrat]
#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)
« Poslední změna: 03 Únor 2010, 21:20:30 od Martin - ViPEr*CZ* »

dadam

  • Člen
  • **
  • Příspěvků: 151
    • Zobrazit profil
Re: aio
« Odpověď #1 kdy: 02 Únor 2010, 22:41:39 »
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  ;)
« Poslední změna: 02 Únor 2010, 22:52:17 od dadam »

Martin - ViPEr*CZ*

Re: aio
« Odpověď #2 kdy: 02 Únor 2010, 23:04:39 »
Todle má být jak?

Kód: [Vybrat]
int j = 0l
  for( j = 0; j < a_size; j++ )

Takhle:

Kód: [Vybrat]
for(int j = 0; j < a_size; j++ )
???
Open source is gold way... Mint 17.2, Debian 8.1 Jessie| Ubuntu Wiki (návody) | Google vyhledávač | Qt4 návody

dadam

  • Člen
  • **
  • Příspěvků: 151
    • Zobrazit profil
Re: aio
« Odpověď #3 kdy: 02 Únor 2010, 23:22:14 »
Povedlo se mi to zprovoznit, tady je kód s opravami:
Kód: [Vybrat]
#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;
}

mizik

  • Návštěvník
  • *
  • Příspěvků: 72
    • Zobrazit profil
    • mizici.com
Re: aio
« Odpověď #4 kdy: 03 Únor 2010, 09:18:12 »
Omlouvam se, pri odstranovani "omacky" kolem, jsem zde udelal preklep.
spravne ma byt....
Kód: [Vybrat]
int j = 0;

Martin - ViPEr*CZ*

Re: aio
« Odpověď #5 kdy: 03 Únor 2010, 09:24:17 »
Ono když to int šoupnete rovnou do tý závorky k for, tak ušetříte v kódu jeden řádek  ;)
Open source is gold way... Mint 17.2, Debian 8.1 Jessie| Ubuntu Wiki (návody) | Google vyhledávač | Qt4 návody

mizik

  • Návštěvník
  • *
  • Příspěvků: 72
    • Zobrazit profil
    • mizici.com
Re: aio
« Odpověď #6 kdy: 03 Únor 2010, 09:27:02 »
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:
Kód: [Vybrat]
#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;
}
« Poslední změna: 03 Únor 2010, 09:31:59 od mizik »

mizik

  • Návštěvník
  • *
  • Příspěvků: 72
    • Zobrazit profil
    • mizici.com
Re: aio
« Odpověď #7 kdy: 03 Únor 2010, 09:28:34 »
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. ::)

mizik

  • Návštěvník
  • *
  • Příspěvků: 72
    • Zobrazit profil
    • mizici.com
Re: aio
« Odpověď #8 kdy: 03 Únor 2010, 09:31:29 »
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...
« Poslední změna: 03 Únor 2010, 09:35:21 od mizik »

Martin - ViPEr*CZ*

Re: aio
« Odpověď #9 kdy: 03 Únor 2010, 09:42:56 »
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 ;)
Open source is gold way... Mint 17.2, Debian 8.1 Jessie| Ubuntu Wiki (návody) | Google vyhledávač | Qt4 návody

mizik

  • Návštěvník
  • *
  • Příspěvků: 72
    • Zobrazit profil
    • mizici.com
Re: aio
« Odpověď #10 kdy: 03 Únor 2010, 09:51:33 »
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...)
« Poslední změna: 03 Únor 2010, 09:53:57 od mizik »

dadam

  • Člen
  • **
  • Příspěvků: 151
    • Zobrazit profil
Re: aio
« Odpověď #11 kdy: 03 Únor 2010, 10:05:39 »
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).

mizik

  • Návštěvník
  • *
  • Příspěvků: 72
    • Zobrazit profil
    • mizici.com
Re: aio
« Odpověď #12 kdy: 03 Únor 2010, 10:15:18 »
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
« Poslední změna: 03 Únor 2010, 10:19:15 od mizik »

dadam

  • Člen
  • **
  • Příspěvků: 151
    • Zobrazit profil
Re: aio
« Odpověď #13 kdy: 03 Únor 2010, 10:30:33 »
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.

mizik

  • Návštěvník
  • *
  • Příspěvků: 72
    • Zobrazit profil
    • mizici.com
Re: aio
« Odpověď #14 kdy: 03 Únor 2010, 10:41:10 »
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....
« Poslední změna: 03 Únor 2010, 10:44:37 od mizik »

Martin - ViPEr*CZ*

Re: aio
« Odpověď #15 kdy: 03 Únor 2010, 10:50:00 »
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 ???
Open source is gold way... Mint 17.2, Debian 8.1 Jessie| Ubuntu Wiki (návody) | Google vyhledávač | Qt4 návody

dadam

  • Člen
  • **
  • Příspěvků: 151
    • Zobrazit profil
Re: aio
« Odpověď #16 kdy: 03 Únor 2010, 11:07:18 »
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š?

mizik

  • Návštěvník
  • *
  • Příspěvků: 72
    • Zobrazit profil
    • mizici.com
Re: aio
« Odpověď #17 kdy: 03 Únor 2010, 16:55:12 »
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
Kód: [Vybrat]
myaiocb.aio_sigevent.sigev_notify = SIGEV_THREAD;//SIGEV_CALLBACK
myaiocb.aio_sigevent.sigev_notify_function = aio_completion_handler;//nastavim callback

ktery muze vypadat nasledovne:
Kód: [Vybrat]
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 )