nixp.ru v3.0

18 января 2017,
среда,
04:43:47 MSK

DevOps с компанией «Флант»
aspolyakov написал 19 ноября 2007 года в 17:10 (475 просмотров) Ведет себя как мужчина; открыл 2 темы в форуме, оставил 9 комментариев на сайте.

Читал статьи по aio, решил сделать свой простой вариант с динамически определямым числом запросов.

http://www.opennet.ru/opennews/art.shtml?num=8275

Тестировал на дарвине и на фрибсд61, на дарвине, до 16 операций нормально, потом все с ошибкой, а на фряхе сразу Invalid System call.

Посоветуйте как лучше писать и что сдесь не правильно?

Спасибо, за внимание))

using namespace std;

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

int main(void)

{

int fd_out, ret;

int requests_count=19,ii=0,buffer_size=4089;

aiocb ** requests = new aiocb * [requests_count];

if((fd_out=open(«/master.htm»,O_RDWR)) == -1)

{

fprintf(stderr,"Open failed:%s (errno=%d)\n»,strerror(errno),errno);

exit(EXIT_FAILURE);

}

//for (ii=0;ii<4;ii++) fprintf(stdout,«test2\n»);

ii=0;

for (ii=0;ii

{

requests[ii]=new aiocb;

bzero( (char *)requests[ii], sizeof(struct aiocb) );

requests[ii]->aio_fildes=fd_out;

requests[ii]->aio_nbytes = buffer_size;

requests[ii]->aio_buf=new char[buffer_size];

requests[ii]->aio_lio_opcode = LIO_READ;

requests[ii]->aio_offset = buffer_size*ii;

}

int code=0;

ret = lio_listio( LIO_NOWAIT, requests, requests_count, NULL );

if(ret<0)perror(«lio_listio»);

int progress=0,retval=0;

for (ii=0;ii

{

code=aio_error( requests[ii] );

if ( code == EINPROGRESS )

{

progress++;

}

else

if(code<0)perror(«read failed!»);

fprintf(stdout,"request:%d timeout%d\n»,ii,progress);

progress=0;

}

for (ii=0;ii

{

fprintf(stdout,(char*)requests[ii]->aio_buf );

delete((char *)requests[ii]->aio_buf);

}

close(fd_out);

return 0;

metal

Замечание по освобождению памяти delete[] а не просто delete при освобождении массива и где delete для остальной памяти выделенной динамически? Также нет обработки exception, но для примера не очень важно. В твоем примере не хватает ожидания, добавь sleep после lio_listio, без него у меня успевает обработаться 10-12 операций. Интересно, что linux начинает обрабатывать с конца массива операций, так первые (без sleep) 6-7 не выполнены, а последние успешны. Поскольку я читал из /dev/zero, то содержимое не выводил в консоль. Тест запускал на :

Linux 2.6.23.1-21.fc7 #1 SMP Thu Nov 1 21:09:24 EDT 2007 i686 i686 i386 GNU/Linux.

По поводу твоих неудачных тестов: предположу что на дарвин 16 просто ограничение.

Фряха твоя просто не имеет поддежки aio, не знаю что там в ней надо допилить для ее включения, похоже ядро собрано без aio.

aspolyakov

delete((char *)requests[ii]->aio_buf);   Сдесь я удаляю выделенную пямять под структуры, а про сам массив указателей забыл. те надо добавить delete requests; вконце?

delete (char*)requests[ii]->aio_buf;//Удаляю строки

delete requests[ii];//Удаляю структуры

и это в последнем цикле?

aspolyakov

Это новая версия подсчитывает задержки для каждого запроса и похожже на бсд системах запросы обрабатываются с начала и не параллельно.

Request N0 timeout=919

Request N1 timeout=927

Request N2 timeout=937

Request N3 timeout=991

Request N4 timeout=1019

Request N12 timeout=1836

Request N13 timeout=4541

Request N14 timeout=6223

Request N15 timeout=10584

int main(void)

{

int fd_out, ret;

int requests_count=16,ii=0,buffer_size=4089;

aiocb ** requests = new aiocb * [requests_count];

if((fd_out=open(«/master.htm»,O_RDWR)) == -1)

{

     fprintf(stderr,"Open failed:%s (errno=%d)\n»,strerror(errno),errno);

     exit(EXIT_FAILURE);

}

//for (ii=0;ii<4;ii++)      fprintf(stdout,«test2\n»);

ii=0;

int progress[requests_count];

for (ii=0;ii

{

     progress[ii]=0;

     requests[ii]=new aiocb;//Создаю структуры и адреса записываются в ячейку массива

     bzero( (char *)requests[ii], sizeof(struct aiocb) );

     requests[ii]->aio_fildes=fd_out;

     requests[ii]->aio_nbytes = buffer_size;

     requests[ii]->aio_buf=new char[buffer_size];

     requests[ii]->aio_lio_opcode = LIO_READ;

     requests[ii]->aio_offset = buffer_size*ii;

}

int code=0;

ret = lio_listio( LIO_NOWAIT, requests, requests_count, NULL );

//sleep(6);

if(ret<0)perror(«lio_listio»);

int flag=1;

while (flag==1)

{

     flag=1;

     for (ii=0;ii

     {

           code=aio_error( requests[ii] );

           if ( code == EINPROGRESS )

                 {

                       progress[ii]++;

                       flag=1;

                 }

           else

                 {

                       flag=0;

                       if(code<0)perror(«Aio read failed! »);

                 }

     }

}

for (ii=0;ii

{

     //fprintf(stdout,(char*)requests[ii]->aio_buf );

     delete (char*)requests[ii]->aio_buf;//Удаляю строки

     delete requests[ii];//Удаляю структуры

     fprintf(stdout,"\nRequest N%d timeout=%d\n»,ii,progress[ii]);

}

delete requests;//Удаляю массив указателей, который забыл удалить. Что я еще забыл?

close(fd_out);

return 0;

}

//EOF

metal
aspolyakov
delete((char *)requests[ii]->aio_buf); Сдесь я удаляю выделенную пямять под структуры, а про сам массив указателей забыл.



requests[ii]->aio_buf=new char[buffer_size];

Здесь массив, значит

delete[]



requests[ii] = new aiocb;

Здесь стуктура, значит

delete


для каждой структуры

aiocb ** requests = new aiocb * [requests_count];

Здесь массив, значит

delete[]

Второй пример позже гляну, сейчас нет времени и не забывай про exception, сразу не привыкнешь их обрабатывать, потом все время будешь косячить. В данном примере вероятность их возникновение стремится к нулю, но в серьезной разработке new может проваливаться только так.

aspolyakov

Я правильно донал?

for (ii=0;ii

{

//fprintf(stdout,(char*)requests[ii]->aio_buf );

delete [](char*)requests[ii]->aio_buf;//Удаляю строки

delete requests[ii];

fprintf(stdout,"\nRequest N%d timeout=%d\n»,ii,progress[ii]);

}

delete requests[requests_count];

Спасибо за советы))

metal
aspolyakov
Я правильно донал?

Не совсем,

delete[] requests;

Размер массива при удалении писать не надо, это требовалось в совсем древних компиляторах С, честно в живую таких не встречал.

Просто надо использовать правильный оператор. delete для одиночных объектов и delete[] для массивов.

metal

linux выполняет параллельно, причем задом на перед:

Request N0 timeout=6587

Request N1 timeout=6587

Request N2 timeout=6587

Request N3 timeout=6587

Request N4 timeout=6587

Request N5 timeout=6586

Request N6 timeout=6586

Request N7 timeout=6586

Request N8 timeout=6586

Request N9 timeout=6586

Request N10 timeout=6586

Request N11 timeout=6586

Request N12 timeout=6586

Request N13 timeout=6586

Request N14 timeout=6586

Request N15 timeout=6586

Request N16 timeout=6586

Request N17 timeout=6586

Linux zaratustra 2.6.23.8 #3 Sat Nov 17 13:52:30 MSK 2007 i686 Intel(R) Pentium(R) M processor 1.60GHz GenuineIntel GNU/Linux

Это другая машина, но думаю на всех одинаково.

aspolyakov

Почему наоборот-то? если для вызовов 0,1,2,3,4 задержка меньше всего? если меньше задержка значит выполняется они в первую очередь.

Я почитал про исключения, понял что выявление ошибок через errno модет превратится в катачтрофу при многопоточных вычисления. Где можно посмотреть пример работы системного вызова и исключений? Кстати есть ли какие готовые оболчки для сист вызовов? чтобы велосипед не изобретать.

По поводу delete, компилятор нельзя заставить следить за такими ошибками? что бывает, если не тот оператор? строка char[buffer_size] это тоже массив?

metal
aspolyakov
Почему наоборот-то? если для вызовов 0,1,2,3,4 задержка меньше всего? если меньше задержка значит выполняется они в первую очередь.

Так вот задержка меньше всего для последних буферов в случае linux.

Я почитал про исключения, понял что выявление ошибок через errno модет превратится в катачтрофу при многопоточных вычисления. Где можно посмотреть пример работы системного вызова и исключений? Кстати есть ли какие готовые оболчки для сист вызовов? чтобы велосипед не изобретать.

Современные библиотеки имеют свой errno на каждый поток, так что катастрофы не будет. Делать обертки для большинства системных вызовов нет никакго смысла, ошибки все-равно проверять надо. Есть книжка Стивенсона «Разработка сетевых предложений под linux» (надеюсь правильно написал), там рассматриваются примеры оберток для системных вызовов.

По поводу delete, компилятор нельзя заставить следить за такими ошибками?


Компилятор нельзя, но можно заставить это делать всякие auto_ptr.

что бывает, если не тот оператор?

Зависит от реализации, но чаще всего утечка памяти.

строка char[buffer_size] это тоже массив?


это статический массив, в любой книжке по C можно прочитать об этом подробно.

ecobeingecobeing.ru
Экология и вегетарианство на благо всем живым существам Планеты.