LinuxForum.Fans
Тема

Порок Ubuntu

Автор: Peter 94 сообщений 6673 просмотров
26.01.2015 21:39 #411445

Я уже жаловался, что в Ubuntu-14.04 в Qt таймер неточно отрабатывает
заданный интервал, вместо 4000ms проходит 4063.
Сегодня обнаружилась ещё более странная вещь уже в консоли в программе на C.
Это маленькая тестовая программа, там сначала создаётся udp-сокет, для него
запускается recvfrom и ждёт обращения, а когда оно приходит, то с помощью
sendto отсылает его обратно. Затем там в цикле передаётся некий массив, но
это несущественно. Оказалось, что, если после выполнения sendto вставить
вызов gettimeofday, всё равно, перед циклом или внутри, то sendto ничего
не пересылает и заканчивется с ошибкой 22 и возвращает -1.

Т.е. только присутствие в тексте программы gettimeofday приводит
к неработоспособности. В Astra Linux, основанной на Debian Wheezy,
и то и другое работает правильно.

Пётр.

28.01.2015 13:25 #411772

1. думаю стоит установить lowlatency ядро, если Вы хотите точного тайминга.

text
name -a
Linux asm-B113 3.16.0-29-lowlatency #39-Ubuntu SMP PREEMPT Tue Dec 16 21:12:19 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
28.01.2015 13:30 #411775

Peter, где код?

"Peter" написал:
Я уже жаловался, что в Ubuntu

ССЗБ.

28.01.2015 14:00 · отредактировано #411783
Харитон написал:
1. думаю стоит установить lowlatency ядро, если Вы хотите точного тайминга.
text
name -a
Linux asm-B113 3.16.0-29-lowlatency #39-Ubuntu SMP PREEMPT Tue Dec 16 21:12:19 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

Ядро скомпилировано с LOWLATENCY и HZ=1000.

Пётр.

drBatty написал:
Peter, где код?

[quote="Peter"]Я уже жаловался, что в Ubuntu

ССЗБ.[/quote]
Приведу попозже, но там именно то, что я описал: помещение gettimeofday() после sendto()
каким-то образом на неё влияет.

Пётр.

28.01.2015 14:07 #411785

"Peter" написал:
Приведу попозже, но там именно то, что я описал: помещение gettimeofday() после sendto()
каким-то образом на неё влияет.
вангую, что вы как-то не правильно делаете, и добились UB.
28.01.2015 16:58 · отредактировано #411807

drBatty написал:
[quote="Peter"]Приведу попозже, но там именно то, что я описал: помещение gettimeofday() после sendto()
каким-то образом на неё влияет.
вангую, что вы как-то не правильно делаете, и добились UB.[/quote]
Однако в Astra Linux (Debian Wheezy), эта программа работает. Вот её код с отступами:
text

#include <sys/uio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <bool.h>
//#include <cam_udp.h>
typedef union uns_short_int {
    unsigned short int us;
    unsigned char ch[2];
} uns_short_int;
int main() {
    struct timeval tv1, tv2;
    unsigned long long int nt1;
    uns_short_int usi;
    socklen_t lenf;
    int i, j, m1, n, ncyc, nfdc, nj, nfds, nfd, nr, len, lencp, lenj;
    bool b;
    char buf[192];
    unsigned char bufr[1024];
    unsigned short int uvp = 50616, ucp = 50700;    //ucp=COMMAND_PORT;
    unsigned int usc = 62;
    struct sockaddr_in addrcs, addrcc, addrvs;
    FILE *fin, *fout;
  llen:len = sizeof(struct sockaddr_in);
    if (len == 0)
    goto llen;
    fin = fopen("imit_cam_cyc.in", "r");
    if (fin != NULL) {
    n = fscanf(fin, "%hu%[^\n]", &uvp, buf);
    n = fscanf(fin, "%u%[^\n]", &usc, buf);
    n = fscanf(fin, "%d%[^\n]", &ncyc, buf);
    n = fscanf(fin, "%s%[^\n]", buf, buf + 20);
    fclose(fin);
    } else {
    strcpy(buf, "127.0.0.1");
    ncyc = 0;
    }
    usi.us = 0;
    b = true;
    usc *= 1000;
    fout = fopen("imit_cam_cyc.out", "w");
    lencp = 32;            //lencp=sizeof(CONTROL_PACKET);
    fprintf(fout, "input: %d %d  %u %hu %d\n", len, lencp, usc, uvp, ncyc);
    fflush(fout);
    bzero((void *) &addrcs, len);
    bzero((void *) &addrcc, len);
    bzero((void *) &addrvs, len);
    addrcs.sin_addr.s_addr = INADDR_ANY;
    addrcs.sin_family = AF_INET;
    addrcs.sin_port = htons(ucp);
    nfdc = socket(AF_INET, SOCK_DGRAM, 0);
    n = bind(nfdc, (struct sockaddr *) &addrcs, len);
    if (n < 0) {
    strcpy(buf, strerror(errno));
    fprintf(fout, "bind: %d %s\n", errno, buf);
    }

while (b) { n = recvfrom(nfdc, bufr, lencp, MSG_WAITALL, (struct sockaddr *) &addrcc, &lenf); if (n < 0) { strcpy(buf, strerror(errno)); fprintf(fout, "recvrom: %d %s\n", errno, buf); fflush(fout); return 0; } if (n == lencp) { fprintf(fout, "request: %d %d\n", n, nfdc); fflush(fout); n = sendto(nfdc, bufr, lencp, MSG_DONTROUTE, (struct sockaddr *) &addrcc, len); fprintf(fout, "answer: %d\n", n); fflush(fout); if (n != lencp) { strcpy(buf, strerror(errno)); fprintf(fout, "sendto: %d %s\n", errno, buf); fflush(fout); return 0; } b = 0; } } addrvs = addrcc; addrvs.sin_port = htons(uvp); nfds = socket(AF_INET, SOCK_DGRAM, 0); strcpy(buf + 20, "/home/operator1/work/jpg300/jpg_udp_000"); nj = 20 + strlen(buf + 20);

while (1) { for (j = 0; j < ncyc; j++) { sprintf(buf + nj - 3, "%03d", j); nfd = open(buf + 20, O_RDONLY); if (nfd < 0) { strcpy(buf, strerror(errno)); fprintf(fout, "open: %d %s\n", errno, buf); fflush(fout); return 0; } lenj = lseek(nfd, 0, SEEK_END); n = lseek(nfd, 0, SEEK_SET); nr = lenj / 1024; if (nr * 1024 != lenj) { fprintf(fout, "lenj: %d %d %s\n", j, lenj, buf + 20); fflush(fout); } gettimeofday(&tv1, NULL); for (i = 0; i < nr; i++) { n = read(nfd, bufr, 1024); bufr[2] = usi.ch[1]; bufr[3] = usi.ch[0]; n = sendto(nfds, bufr, 1024, MSG_DONTROUTE, (struct sockaddr *) &addrvs, len); if (n < 0) { strcpy(buf, strerror(errno)); fprintf(fout, "sendto: %d %d %s\n", i, errno, buf); fflush(fout); } usi.us++; } close(nfd); gettimeofday(&tv2, NULL); nt1 = (tv2.tv_sec - tv1.tv_sec) * 1000000 + tv2.tv_usec - tv1.tv_usec; m1 = nt1; n = usleep(usc - m1); if (n < 0) { strcpy(buf, strerror(errno)); fprintf(fout, "usleep: %d %d %s\n", i, errno, buf); fflush(fout); } } } fclose(fout); return 0; }

А вот её код в удобном для меня виде:

text

#include <sys/uio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <bool.h>
//#include <cam_udp.h>
typedef union uns_short_int{
  unsigned short int us;
  unsigned char ch[2];
}uns_short_int;
int main() {
struct timeval tv1,tv2;
unsigned long long int nt1;
uns_short_int usi;
socklen_t lenf;
int i,j,m1,n,ncyc,nfdc,nj,nfds,nfd,nr,len,lencp,lenj;
bool b;
char buf[192];
unsigned char bufr[1024];
unsigned short int uvp=50616,ucp=50700;    //ucp=COMMAND_PORT;
unsigned int usc=62;
struct sockaddr_in addrcs,addrcc,addrvs;
FILE *fin,*fout;
llen:  len=sizeof(struct sockaddr_in);if(len==0)goto llen;
 fin=fopen("imit_cam_cyc.in","r");if(fin!=NULL){n=fscanf(fin,"%hu%[^\n]",&uvp,
  buf); n=fscanf(fin,"%u%[^\n]",&usc,buf); n=fscanf(fin,"%d%[^\n]",&ncyc,buf);
  n=fscanf(fin,"%s%[^\n]",buf,buf+20); fclose(fin);}
  else{strcpy(buf,"127.0.0.1");ncyc=0;}usi.us=0;b=true;usc*=1000;
 fout=fopen("imit_cam_cyc.out","w"); lencp=32;    //lencp=sizeof(CONTROL_PACKET);
fprintf(fout,"input: %d %d  %u %hu %d\n",len,lencp,usc,uvp,ncyc);fflush(fout);
 bzero((void*)&addrcs,len);bzero((void*)&addrcc,len);bzero((void*)&addrvs,len);
 addrcs.sin_addr.s_addr=INADDR_ANY;addrcs.sin_family=AF_INET;
 addrcs.sin_port=htons(ucp);nfdc=socket(AF_INET,SOCK_DGRAM,0);
 n=bind(nfdc,(struct sockaddr*)&addrcs,len);
 if(n<0){strcpy(buf,strerror(errno));fprintf(fout,"bind: %d %s\n",errno,buf);}

while(b){n=recvfrom(nfdc,bufr,lencp,MSG_WAITALL,(struct sockaddr*)&addrcc,&lenf );if(n<0){strcpy(buf,strerror(errno));fprintf(fout,"recvrom: %d %s\n",errno, buf);fflush(fout);return 0;}if(n==lencp){ fprintf(fout,"request: %d %d\n",n,nfdc);fflush(fout); n=sendto(nfdc,bufr,lencp,MSG_DONTROUTE,(struct sockaddr*)&addrcc,len); fprintf(fout,"answer: %d\n",n);fflush(fout); if(n!=lencp){strcpy(buf,strerror(errno));fprintf(fout,"sendto: %d %s\n", errno,buf);fflush(fout);return 0;}b=0;}} addrvs=addrcc;addrvs.sin_port=htons(uvp); nfds=socket(AF_INET,SOCK_DGRAM,0); strcpy(buf+20,"/home/operator1/work/jpg300/jpg_udp_000");nj=20+strlen(buf+20);

while(1){for(j=0;j<ncyc;j++){sprintf(buf+nj-3,"%03d",j); nfd=open(buf+20,O_RDONLY); if(nfd<0){strcpy(buf,strerror(errno));fprintf(fout,"open: %d %s\n",errno,buf); fflush(fout);return 0;} lenj=lseek(nfd,0,SEEK_END);n=lseek(nfd,0,SEEK_SET);nr=lenj/1024; if(nr*1024!=lenj){fprintf(fout,"lenj: %d %d %s\n",j,lenj,buf+20);fflush(fout);} gettimeofday(&tv1,NULL);for(i=0;i<nr;i++){n=read(nfd,bufr,1024); bufr[2]=usi.ch[1];bufr[3]=usi.ch[0]; n=sendto(nfds,bufr,1024,MSG_DONTROUTE,(struct sockaddr*)&addrvs,len); if(n<0){strcpy(buf,strerror(errno));fprintf(fout,"sendto: %d %d %s\n",i, errno,buf);fflush(fout);}usi.us++;}close(nfd);gettimeofday(&tv2,NULL); nt1=(tv2.tv_sec-tv1.tv_sec)*1000000+tv2.tv_usec-tv1.tv_usec;m1=nt1; n=usleep(usc-m1);if(n<0){strcpy(buf,strerror(errno));fprintf(fout, "usleep: %d %d %s\n",i,errno,buf);fflush(fout);}}}fclose(fout); return 0; }

Там включается bool.h, это

text

#ifndef BOOL_H
#define BOOL_H 1

typedef int bool; #define true 1 #define false 0

#endif

Если gettimeofday() поместить, например, перед 2-м while(), то sendto() возвращает -1 и заканчивается с ошибкой 22.
То же самое в варианте программы без цикла после sendto(), вернее, когда в цикле всё время передаётся один и тот же файл.
jpg_udp_nnn - это файлы, состоящие из udp-пакетов для очередного jpg, но это не важно, важно, что gettimeofday()
влияет на предидущий вызов sendto().

Пётр.

28.01.2015 17:16 #411810

ошибка 22 - это EINVAL. Ищите у себя: либо что-то неправильно вызываете, либо нагадили в память (переполнился какой-нибудь буфер)
Я в вашем "кирпиче" ничего не нашёл, но особо внимательно и не проверял.

28.01.2015 18:11 #411821

"Peter" написал:
FILE *fin, *fout; llen:len = sizeof(struct sockaddr_in); if (len == 0) goto llen;
досвидания. Увидимся в следующей жизни, когда вы научитесь писать.
28.01.2015 20:05 #411842

drBatty написал:
[quote="Peter"] FILE *fin, *fout; llen:len = sizeof(struct sockaddr_in); if (len == 0) goto llen;
досвидания. Увидимся в следующей жизни, когда вы научитесь писать.[/quote]
Это игра ума. Ещё раньше я замечал, что для struct sockaddr_in sizeof() часто возвращает
0 или -1, уже не помню. И зачем я буду себя ограничивать в коде?

Пётр.
28.01.2015 20:53 #411856

"Peter" написал:
И зачем я буду себя ограничивать в коде?
не, не нужно. Наоборот.
Вам сюда
28.01.2015 22:03 #411876

Peter написал:
[quote=drBatty][quote="Peter"] FILE *fin, *fout; llen:len = sizeof(struct sockaddr_in); if (len == 0) goto llen;
досвидания. Увидимся в следующей жизни, когда вы научитесь писать.[/quote]
Это игра ума. Ещё раньше я замечал, что для struct sockaddr_in sizeof() часто возвращает
0 или -1, уже не помню. И зачем я буду себя ограничивать в коде?

Пётр.[/quote] да ладно! sizeof() действительно вычисляется не при компиляции, а при исполнении, но вернуть ерунду он никак не может. Во всяком случае переспрашивать его бесполезно. Кстати, объекты длины 0 вполне допустимы.
Но речь здесь о другом: этот кусок действительно странный, но он законный, так что обсуждать эту часть есть смысл только после того, как всё заработает.
28.01.2015 22:49 · отредактировано #411878
s.xbatob написал:
[quote=Peter][quote=drBatty]досвидания. Увидимся в следующей жизни, когда вы научитесь писать.

Это игра ума. Ещё раньше я замечал, что для struct sockaddr_in sizeof() часто возвращает
0 или -1, уже не помню. И зачем я буду себя ограничивать в коде?

Пётр.[/quote] да ладно! sizeof() действительно вычисляется не при компиляции, а при исполнении, но вернуть ерунду он никак не может. Во всяком случае переспрашивать его бесполезно. Кстати, объекты длины 0 вполне допустимы.
Но речь здесь о другом: этот кусок действительно странный, но он законный, так что обсуждать эту часть есть смысл только после того, как всё заработает.[/quote]
Замечал опять же в Ubuntu в этой программе. Однако этот кусок работает и в Ubuntu
и в Debian, поскольку выход из него происходит.

Пётр.

drBatty написал:
[quote="Peter"]И зачем я буду себя ограничивать в коде?
не, не нужно. Наоборот.
Вам сюда[/quote]
Я там не вникал, но cin и cout с перенаправлением я никогда не использую,
употребляю только fprintf.

Пётр.
29.01.2015 08:00 #411915

Peter, то, что ваш код "тут работает, там не работает", очевидно с первых строк. Можно даже не компилировать.

"Peter" написал:
Я там не вникал
это сайт о том, как НЕ НАДО писать.
29.01.2015 12:45 #411959

drBatty написал:
Peter, то, что ваш код "тут работает, там не работает", очевидно с первых строк. Можно даже не компилировать.

[quote="Peter"]Я там не вникал
это сайт о том, как НЕ НАДО писать.[/quote]
Это и по названию понятно. Обычно я стараюсь оптимизировать время выполнения.

Пётр.
29.01.2015 13:16 · отредактировано #411961
"Peter" написал:
Обычно я стараюсь оптимизировать время выполнения.
преждевременная оптимизация — всегда зло(не я сказал).
И ваш "код" это доказывает на все 146%. Он не просто медленно работает, а часто вообще не работает.
И не нужно валить с больной головы на здоровую, Ubuntu тут совсем не причём.


PS:
"Peter" написал:
Обычно я стараюсь оптимизировать время выполнения.

очевидно, вы даже не знаете, что это такое, "время выполнения". Доказательство

text
  llen:len = sizeof(struct sockaddr_in);
    if (len == 0)
    goto llen;

лично мне это УГ даже неловко в {code} оборачивать.

"s.xbatob" написал:
sizeof() действительно вычисляется не при компиляции, а при исполнении
в C/C++ таки при компиляции. Это константа в рантайме. У вас опечатка что-ли?

"s.xbatob" написал:
Кстати, объекты длины 0 вполне допустимы.
да. Как Невидимый Розовый Единорог.

"s.xbatob" написал:
этот кусок действительно странный
он не странный, он не имеет смысла.

"s.xbatob" написал:
но он законный
в том смысле, что существует компилятор, который из этого УГ может сделать какие-то байтики, а потом этим байтикам можно передать исполнение?
29.01.2015 13:58 #411966

Я же сказал, что это игра ума. Тем более я не знал, почему sizeof() возвращала 0, вот и хотел это проверить - будет 0 или нет.
И это не настоящая программа для работы, она была написана для проверки одного предположения.

Пётр.

29.01.2015 14:17 #411973
"Peter" написал:
Я же сказал, что это игра ума
это плохая игра.

"Peter" написал:
Тем более я не знал, почему sizeof() возвращала 0

во первых, sizeof ничего не возвращает, это константа. Но в отличиеот других констант, её значение не известно программисту во время написания кода.

Вот пример использования этой константы:

text
int* val = malloc(sizeof(int));

в коде никаких sizeof НЕ будет, а будет просто malloc(8), если у вас int имеет размер в 8 байт. Важно понимать, что sizeof возвращает размер в char'ах, а это не байты.

Во вторых, если у вас sizeof "возвращает" ноль, то вы явно что-то делаете не так. Зачем вам объект, которого нет?

В третьих, ваша "программа" не нужна(никому). Т.к. это write-only макароны.

29.01.2015 14:20 #411975

Рекомендую прочитать цикл статей о работе анализатора PVS-Studio.
Про lowlatency выше уже сказали вроде.

29.01.2015 17:50 #411997

Хорошо, я не задумывался, является ли sizeof() исполнимым оператором. До сих пор с ним не былотрудностей.

Пётр.

29.01.2015 22:03 #412038

"Peter" написал:
Хорошо, я не задумывался, является ли sizeof() исполнимым оператором. До сих пор с ним не былотрудностей.
зачем вы задумывались об оптимизации того, чего не понимаете?

goto, кстати, практически НЕ оптимизируется, а вот цикл while компилятор с радостью выкинет (потому, можно написать не нужный цикл, если вам так понятнее и "читаемие", но вот ненужное goto нельзя писать ни в коем разе).

Вот смотрите:
text
int factorial(int x)
{
    return x<=1? 1: x*factorial(x-1);
}

вы наверное скажите, что это "плохой код", да? Неоптимизированный, да? Работать будет медленно?

Хорошо, а вот этот:

text
 8048377:   bb 01 00 00 00          mov    ebx,0x1
 804837c:   eb 04                   jmp    8048382 <main+0x52>
 804837e:   66 90                   xchg   ax,ax
 8048380:   89 d0                   mov    eax,edx
 8048382:   8d 50 ff                lea    edx,[eax-0x1]
 8048385:   0f af d8                imul   ebx,eax
 8048388:   83 fa 01                cmp    edx,0x1
 804838b:   75 f3                   jne    8048380 <main+0x50>

как оно вам?

ВНЕЗАПНО: второй код — это и есть первый, только после обработки gcc,
Спрашивается, а зачем нужно было обмазываться goto, если компилятор сам умеет ими обмазываться?

Войдите или зарегистрируйтесь, чтобы ответить.