Читал статьи по 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;
Последние комментарии
- OlegL, 17 декабря в 15:00 → Перекличка 21
- REDkiy, 8 июня 2023 года в 9:09 → Как «замокать» файл для юниттеста в Python? 2
- fhunter, 29 ноября 2022 года в 2:09 → Проблема с NO_PUBKEY: как получить GPG-ключ и добавить его в базу apt? 6
- Иванн, 9 апреля 2022 года в 8:31 → Ассоциация РАСПО провела первое учредительное собрание 1
- Kiri11.ADV1, 7 марта 2021 года в 12:01 → Логи catalina.out в TomCat 9 в формате JSON 1
Замечание по освобождению памяти 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.
delete((char *)requests[ii]->aio_buf); Сдесь я удаляю выделенную пямять под структуры, а про сам массив указателей забыл. те надо добавить delete requests; вконце?
delete (char*)requests[ii]->aio_buf;//Удаляю строки
delete requests[ii];//Удаляю структуры
и это в последнем цикле?
Это новая версия подсчитывает задержки для каждого запроса и похожже на бсд системах запросы обрабатываются с начала и не параллельно.
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
Здесь массив, значит
Здесь стуктура, значит
для каждой структуры
Здесь массив, значит
Второй пример позже гляну, сейчас нет времени и не забывай про exception, сразу не привыкнешь их обрабатывать, потом все время будешь косячить. В данном примере вероятность их возникновение стремится к нулю, но в серьезной разработке new может проваливаться только так.
Я правильно донал?
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];
Спасибо за советы))
Не совсем,
Размер массива при удалении писать не надо, это требовалось в совсем древних компиляторах С, честно в живую таких не встречал.
Просто надо использовать правильный оператор. delete для одиночных объектов и delete[] для массивов.
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
Это другая машина, но думаю на всех одинаково.
Почему наоборот-то? если для вызовов 0,1,2,3,4 задержка меньше всего? если меньше задержка значит выполняется они в первую очередь.
Я почитал про исключения, понял что выявление ошибок через errno модет превратится в катачтрофу при многопоточных вычисления. Где можно посмотреть пример работы системного вызова и исключений? Кстати есть ли какие готовые оболчки для сист вызовов? чтобы велосипед не изобретать.
По поводу delete, компилятор нельзя заставить следить за такими ошибками? что бывает, если не тот оператор? строка char[buffer_size] это тоже массив?
Так вот задержка меньше всего для последних буферов в случае linux.
Современные библиотеки имеют свой errno на каждый поток, так что катастрофы не будет. Делать обертки для большинства системных вызовов нет никакго смысла, ошибки все-равно проверять надо. Есть книжка Стивенсона «Разработка сетевых предложений под linux» (надеюсь правильно написал), там рассматриваются примеры оберток для системных вызовов.
Компилятор нельзя, но можно заставить это делать всякие auto_ptr.
Зависит от реализации, но чаще всего утечка памяти.
это статический массив, в любой книжке по C можно прочитать об этом подробно.