LINUX.ORG.RU

Сообщения saper

 

C: с указателями на функции код тормозит

Собственно, subj. Функции View* возвращают указатель на static char *, по сути все три делают double2string преобразование, просто по-разному (некоторые округляют, некоторые добавляют k/M в конце числа). Опции сборки: -O4 -march=i486 -fomit-frame-pointer -std=c99 -lm

char *(* MYview)(double ivalue);

int main(void) {
int i, x = 3;

if (x == 1) MYView = View1;
else if (x == 2) MYView = View2;
else if (x == 3) MYView = View3;

for (i = 0; i < 1000000; i++) fprintf(stdout, "%s\n", MyView(47653423.0));

return 0;
}

Код выше тормознее, чем приведенный ниже на 20% (согласно поля real команды time: 3.300 для кода выше > 2.700 для кода ниже):

int main(void) {
int i, x = 3;

for (i = 0; i < 1000000; i++) {
if (x == 1) fprintf(stdout, "%s\n", View1(47653423.0));
else if (x == 2) fprintf(stdout, "%s\n", View2(47653423.0));
else if (x == 3) fprintf(stdout, "%s\n", View3(47653423.0));

return 0;
}

И если это нормально, тогда может кто то пояснит в каких случаях указатели на функции эффективны?

saper
()

C: макросы

Подсмотрел тут http://www.linux.org.ru/view-message.jsp?msgid=1897145 интересное решение по преобразованию макросов и числового в строковый формат, теперь вот мучаюсь :-)

Макросы в программе сейчас используются для определения размеров массивов, соответственно в fscanf выражения нужно вставлять строковое значение числового макроса за вычетом единицы (согласно man на fscanf ширина поля задется без завершающего '\0').

Нерабочий код (на примере того по ссылке):
#define MAXBETASIZE 1024
#define _s(a) #a
#define _string(a) _s(a)
...
char beta[MAXBETASIZE];
sscanf(bigstring, "%" _string(MAXBETASIZE-1) "s", &beta);

Единицу в последнем случае он не вычитает и ругается при сборке, можно ли препроцессор заставить вычитать её?

saper
()

C: локализация POSIX-way

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

Теперь про локализацию: я так понимаю, что необходимо использовать функции catopen, catclose и catgets (gettext не стандарт для всех систем, кроме Solaris и Linux). Есть несколько вопросов по применению POSIX-функций (я конечно могу опытным путем проверить их в Linux и HP-UX, но это не полный перечень платформ, которые хотелось бы поддерживать, вразумительной документации не нашел):
1. POSIX не определяет, где хранить каталоги (cat-файлы), т.е. catopen конечно читает NLSPATH, но, например, в Slackware Linux ни переменной NLSPATH, ни одного .cat файла я не обнаружил. Вопрос: куда программа по make install должна их забросить и что должна передавать в качестве первого параметра catopen?
2. Правильно ли будет (оч. хочется) сделать массив указателей типа char * и при старте программы заполнить его указателями через catgets? Ведь catgets с номером сообщения мало информативен для кода, да и обременяет программу каждый раз по catgets делать поиск (пусть даже по индексу) в каталоге.
3. К п.2 выше, живут ли значения catgets после очередного вызова catgets? Согласно man из HP-UX и Linux - живут.
4. Согласно man на catgets, сказано, что если catopen не нашел каталога (вернул -1), то будут использоваться значения по-умолчанию для C/POSIX. Правильно ли я понимаю, что через NLSPATH всегда должна быть доступна директория en (или какая? en_US? en_GB???) с локализацией на английском?

P.S. Гуглил, яндексил, читал стандарт, всё весьма противоречиво, кстати, очень ругают *BSD системы :-\

saper
()

GCC: приведение типа отменяет квалификаторы указуемого типа

GCC генерирует предупреждение, описанное в subj для строки с execv. Хочется правильно его избежать (т.е. не отключая предупреждения). Если argsarray переопределить как char *, и убрать преобразование типа в execv, тогда ругается на строку с циклом for, т.к. program является const char *. Есть какой-нибудь красивый способ избежать предупреждений в таком коде:

void MYsystem(const char *program, ...) {
pid_t childpid;
int tmp = 0;
va_list args;
const char *argsarray[MAXARGS];

childpid = fork();
if (childpid == 0) {
va_start(args, program);

for (argsarray[0] = program; (argsarray[tmp] = va_arg(args, char *)) != NULL; tmp++);

execv(program, (char * const *)argsarray);

saper
()

Посоветуйте кроссплатформенную программу для примера

Интересует программа написанная давно, хочется посмотреть код и Makefile без BSD/GNU расширений. А то в одном из Unix руководств по Makefile было сказано, что такое условие: ifneq ($(srcMakefile),yes) вполне себе standard, а make в FreeBSD 4.x ругается на эту строку. К тому же раньше Makefile-ы были короче, а то сейчас после autotools можно с ума сойти разбираясь в зависимостях ;-)

Да и по shell такая же проблема, есть руководства, но они или короткие, или не уточняют соответствует конструкция Bourne SHell или она только для Bourne Again SHell :-\ Просто беда какая то, даже по C вызовам man в Linux не всегда все несовместимости пишет.

saper
()

javascript и unescape с русским

Подскажите как можно декодировать в javascript строку вида: %EA%E0%F2%E5%E3%EE%F0%E8%FF?

unescape не подходит, он только latin-1 на выходе дает, это подтверждает и скрипт:
var enced="http://www.yandex.ru/yandsearch?stype=&nl=0&text=fluke+%EA%E0%F2%E5%E...;
var unenced=unescape(enced);
document.write(unenced);

saper
()

Как записать из консоли с микрофона более 40 минут?

Собственно subj. record обрывается где то на 40 минутах, хотя файл по длине соответствует 2 часам и xmms показывает 2 часа, а winamp - 40 минут. record оставлялся на 8 часов, это время и нужно писать.

К сожалению, что написал record после записи я не видел, но возможно кто то сталкивался и подскажет.

P.S. Пользователь действовал строго по инструкции и выключил компьютер ровно через 8 часов, а не раньше. Перебоев с питанием не было.

saper
()

Обрезать (crop) картинку без перекодирования AVI файла

Как обрезать картинку AVI файла без его перекодирования?

В форуме было уже такое сообщение, но к сожалению ни в mencoder, ни в avidemux2, ни в virtualdub этого сделать не удалось (не нашел ничего, все попытки что то такое сделать были неудачными).

Ведь это возможно, особенно если учесть, что обрезать мне нужно много файлов и одинаково (сверху 64, снизу 48). Мне хоть как то обрезать, можно и 32 кратно.

saper
()

a-la SARG: Поделитесь образцами журналов и мини-опрос

Для проекта, который будет открыт как OpenSource поделитесь пожалуйста образцами журналов следующих демонов/сервисов:
- wu-ftpd
- Postfix (оч. нужен)
- Sendmail
- MS ISA (оч. нужен)
- MS IIS

1. Конфиденциальную информацию в образцах можете заменить любой другой (только чтобы структура не нарушалась).
2. Желательно, чтобы образец включал в себя как минимум 2 записи: одна с кодом ошибки (для www-серверов это 4xx), вторая - обычная.
3. Если журналы в нескольких форматах и они у вас есть, то нужны все.
4. Если у вас есть образец журнала другого популярного сетевого демона/сервиса, то он тоже пригодится.

Что уже есть:
- Common Log Format (CLF), используется apache;
- Combined Log Format, используется apache и thttpd;
- Squid 2.5.x native log format;
- vsftpd;
- qmail.

При желании/необходимости, можно образцы засылать на xsov@netscape.net

Теперь по части опроса:
1. Что вас не устраивает в SARG/LightSquid и их аналогах?
2. Как вы видете группы в этих программах?
3. Какие отчеты будут интересны с точки зрения безопасности?
4. Что бы вы хотели изменить в таких программах (тут пишите всё что угодно)?

P.S. Загонять журналы в СУБД не получится - теряется оперативность :-(
P.P.S. Текущая версия продукта обладает почти всеми возможностями SARG и некоторыми дополнительными, работает минимум в 7 раз быстрее SARG (достигнутый сейчас максимум - 20). Пока не доработаем выкладывать не будем.

saper
()

Как лучше писать коды HTTP

Я про эти коды:
100 Continue
101 Switching Protocols
102 Processing
200 OK
201 Created
202 Accepted
203 Non-Authoritative Information
204 No Content
205 Reset Content
206 Partial Content
207 Multi Status
300 Multiple Choices
301 Moved Permanently
302 Moved Temporarily
...

Есть некая программа на C, которая ведет учет по кодам, сейчас она это делает так:
double ec[602]; /* у squid с 000 до 601 находится 47 кодов */
ec[code] += bytes;

ec конечно не весь тут используется (много неисользуемых элементов), можно сделать таблицу трансляции, типа:
short int ttable[602][2] = { 100, 0 } ...
через которую можно транслировать, что байты с кодом 100 запишутся в ec с номером элемента 0. Но такой массив ttable будет сложен в инициализации (много пустых мест), можно и функцию сделать, которая будет транслировать через такую таблицу.

Я уже подумываю на какой-нибудь математикой для свертки этих 47 кодов в обычный char...

Подскажите, как лучше организовать? Исходники Squid и Apache смотрел, им проще (они сами определяют когда какой код писать, а мне считывать).

saper
()

Исследование производительности *printf и вывода в файл

Ввиду того, что я так и не получил вразумительного ответа тут: http://www.linux.org.ru/view-message.jsp?msgid=1561742 решил провести самостоятельное тестирование. Если есть возможность - протестируйте на своей платформе.

Сначала о платформе, на которой эти тесты проводились:
- CPU: AMD Athlon Thunderbird 850@977 (1956 bogomips);
- RAM: 256Mb PC133@115;
- HDD: 80Gb 7200rpm 8Mb WDC WD800BB-00JHA0 (fw: 05.01C05).
- OS: Slackware Linux 10.2+current;
- KERNEL: 2.6.17 (с www.kernel.org).

Список процессов (не ядерных) перед тестированием:
1215 ? Ss 0:00 /usr/sbin/syslogd
1218 ? Ss 0:00 /usr/sbin/klogd -c 3 -x
1300 ? Ss 0:00 /usr/sbin/gpm -m /dev/mouse -t imps2
1397 tty1 Ss 0:00 -bash
21639 tty1 S+ 0:00 \_ /usr/bin/mc -P /tmp/mc-root/mc.pwd.1397
21640 ? Ss 0:00 \_ cons.saver /dev/vc/1
21641 pts/0 Ss 0:00 \_ bash -rcfile .bashrc
22279 pts/0 R+ 0:00 \_ ps axf
1399 tty3 Ss+ 0:00 /sbin/agetty 38400 tty3 linux
21569 tty2 Ss 0:00 -bash
21589 tty2 S+ 0:00 \_ mcedit /tresult.txt
21590 ? Ss 0:00 \_ cons.saver /dev/vc/2

#include <limits.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>


int main() {
FILE *test;
time_t t1, t2;
char tbuf[8192] = "\000";
int i = 0;

double d1 = 32768.0;
double d2 = 111111111111.0;
double d3 = 22222222222222222222222.0;

char *s1 = "s1";
char *s2 = "s2mid";
char *s3 = "s3 very-very long";

short int si1 = 1;
short int si2 = 256;
short int si3 = 32765;

int i1 = 1;
int i2 = 65536;
int i3 = 1122334455;

char c1 = '1';
char c2 = '[';
char c3 = '\n';


test = fopen("/testfile", "w");

t1 = time(NULL);
while (i++ < 8000001) {
/* 1: sprintf+fputs
sprintf(tbuf, "%c %hd %d <t1> %'.0f %c <text2> %s %d %s <middle text3> %hd %c %'.0f %d %s %'.0f %hd",
c1, si1, i1, d1, c2, s1, i2, s2, si2, c3, d2, i3, s3, d3, si3);
fputs(tbuf, test);*/

/* 2: sprintf+fwrite
sprintf(tbuf, "%c %hd %d <t1> %'.0f %c <text2> %s %d %s <middle text3> %hd %c %'.0f %d %s %'.0f %hd",
c1, si1, i1, d1, c2, s1, i2, s2, si2, c3, d2, i3, s3, d3, si3);
fwrite(tbuf, strlen(tbuf), 1, test);*/

/* 3: fprintf
fprintf(test, "%c %hd %d <t1> %'.0f %c <text2> %s %d %s <middle text3> %hd %c %'.0f %d %s %'.0f %hd",
c1, si1, i1, d1, c2, s1, i2, s2, si2, c3, d2, i3, s3, d3, si3);*/

/* 4: 15x fprintf
fprintf(test, "%c ", c1);
fprintf(test, "%hd ", si1);
fprintf(test, "%d ", i1);
fprintf(test, "<t1> %'.0f ", d1);
fprintf(test, "%c ", c2);
fprintf(test, "<text2> %s ", s1);
fprintf(test, "%d ", i2);
fprintf(test, "%s ", s2);
fprintf(test, "<middle text3> %hd ", si2);
fprintf(test, "%c ", c3);
fprintf(test, "%'.0f ", d2);
fprintf(test, "%d ", i3);
fprintf(test, "%s ", s3);
fprintf(test, "%'.0f ", d3);
fprintf(test, "%hd", si3);*/

/* 5: 15x sprintf+1x fwrite */
sprintf(tbuf, "%c ", c1);
sprintf(&tbuf[strlen(tbuf)], "%hd ", si1);
sprintf(&tbuf[strlen(tbuf)], "%d ", i1);
sprintf(&tbuf[strlen(tbuf)], "<t1> %'.0f ", d1);
sprintf(&tbuf[strlen(tbuf)], "%c ", c2);
sprintf(&tbuf[strlen(tbuf)], "<text2> %s ", s1);
sprintf(&tbuf[strlen(tbuf)], "%d ", i2);
sprintf(&tbuf[strlen(tbuf)], "%s ", s2);
sprintf(&tbuf[strlen(tbuf)], "<middle text3> %hd ", si2);
sprintf(&tbuf[strlen(tbuf)], "%c ", c3);
sprintf(&tbuf[strlen(tbuf)], "%'.0f ", d2);
sprintf(&tbuf[strlen(tbuf)], "%d ", i3);
sprintf(&tbuf[strlen(tbuf)], "%s ", s3);
sprintf(&tbuf[strlen(tbuf)], "%'.0f ", d3);
sprintf(&tbuf[strlen(tbuf)], "%hd", si3);
fwrite(tbuf, strlen(tbuf), 1, test);
}
t2 = time(NULL);
fprintf(stderr, "TIME ELAPSED: %d\n", (int)(t2 - t1));

fclose(test);

return 0;
}

В следующих сообщениях отпишу по каждому алгоритму полученные результаты, m16/a256 - это параметры hdparm.

saper
()

fprintf vs sprintf+fputs

По моим тестам fprintf медленнее fputs+sprintf, то есть быстрее вывести в память всё sprintf-ами и вывести затем в файл одним fputs. Однако на практике в моем приложении это не всегда подтверждается (есть места где fprintf оказывается быстрее sprintf+fputs).

1. От чего зависит скорость работы fprintf (при стандартных размерах буферов, т.е. без игр с setvbuf), и разная ли будет относительная скорость работы fprintf/sprintf+fputs для разных платформ? Или я совсем не прав, потому что тесты выводили информацию на stderr, который я сливал в /dev/null (вроде stderr запрещено буферизовать).

2. Стоит ли fputs заменить на fwrite в случае если sprintf+fputs все-таки лучше?

По коду: рассматриваю использовать ли Nx sprintf+N/50x fputs или Nx fprintf, размер порции частовыводимой информации в файл от 5 до 32 байт (N/50 - это неподтвержденная моя прикидка).

P.S. Поделитесь опытом. Да, программа обрабатывает входящий поток миллионов записей... (wc -l для типового файла выдал 6'896'149).

saper
()

Несовместимость Linux

Как то нехорошо получается:
- ядра в дистрибутивах отличаются;
- glibc в дистрибутивах отличаются;
- версии наборов стандартных библиотек и сами библиотеки тоже отличаются;
- теперь и init-скрипты отличаются...

Все это создает тотальную несовместимость линуксов с линуксами, смотреть противно (ага-ага: "а ты не смотри", мне потом с некоторыми такими обособленными работать).

В 1995 было все куда проще... Slackware и RedHat, притом совместимые на всех уровнях.

P.S. См. http://www.linux.org.ru/view-message.jsp?msgid=1550475

saper
()

Предложение по улучшению работы сайта

Предлагаю:
1. Запретить объявления о работе в Job-Linux, в которых не указано географическое место работы (город или хотя бы регион).
2. Повесить объявление жирным шрифтом при добавлении объявления в раздел Job-Linux о запрете в п.1 и немедленном удалении неудовлетвряющих п.1 объявлений.
3. Модераторам взять на контроль выполнение требований п.1.

Почему:
1. Определенно неудобно для соискателей и неприятно для тех, кто живет в других городах.
2. Пусть жители столичных городов научатся уважать других людей, живущих в нашей стране и соседних городах.

saper
()

Размер бинарника и GCC

Сразу оговорюсь, что сравнение размеров делал после strip (без опций) и опции компиляции для большого C-файла и нескольких одинаковые.

Была некая программа одним большим C-файлом. Вынес одну функцию во новый C-файл, её прототип определил в новом H-файле. Собрал как и раньше, только указал уже не один C-файл для GCC, а два. Бинарник получился меньше. Стал выносить больше C-функций, бинарник стал уменьшаться. Даже вынос глобальных переменных с typedef-ами уменьшил бинарник на несколько байт.

Получается, если на каждую функцию сделать отдельный файл, то бинарник будет совсем маленький?

GCC стандартный, из Slackware.
$gcc -v
Configured with: ../gcc-3.4.6/configure --prefix=/usr --enable-shared --enable-threads=posix --enable-__cxa_atexit --disable-checking --with-gnu-ld --verbose --target=i486-slackware-linux --host=i486-slackware-linux
Thread model: posix
gcc version 3.4.6

Кто не верит, пусть проверит ... на "Hello World" не работает, но на сложном примере - наверняка ;-)

saper
()

Динамически переопределить функцию в C

Поясню, чего хочется на примере (не имеет никакого отношения к моей программе):

void SHOW_LIST(char *command);

void myf1(char *command)
{
system(command);
}

void myf2(char *)
{
printf(command);
}

void main()
{
SHOW_LIST = myf1;

SHOW_LIST("ls");
}

saper
()

PME-Enable и setpci

Подскажите, как установить флаг PME-Enable, выводимый по lspci -vv при помощи setpci?

Есть такая информация из pci-utils:
#define PCI_PM_CTRL 4 /* PM control and status register */
...
#define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */
...
t = get_conf_word(d, where + PCI_PM_CTRL);
printf("\t\tStatus: D%d PME-Enable%c DSel=%d DScale=%d PME%c\n",
t & PCI_PM_CTRL_STATE_MASK,
FLAG(t, PCI_PM_CTRL_PME_ENABLE),
...

Я так понимаю, что нужно для выбранного устройства (setpci -d или -s) установить для регистра 4 значение 3 бита в 1. Не хочется повредить железку.

Это нужно, чтобы работал Wake-On-Lan на сетевом адаптере. После выключения из Windows он работает (там в настройках PME-Enable стоит в Enabled), после выключения из Linux - нет.

Установка через "ethtool -s eth0 wol g" не помогает (да и не должна, она всего лишь включает WOL на карте, но карта скажем так пока еще не имеет связи с матплатой, потому что PME-Enable выключен - lspci показывает PME-Enable-). В BIOS-е WOL для этой почти интегрированной сетевой платы включен (это Intel EtherExpress VE/100 на IBM T23). Даже если сбросить "ethtool -s eth0 wol d", а потом включить WOL "ethtool -s eth0 wol g", то все равно ничего не работает. Другие флаги для ethtool параметра wol эта сетевая не поддерживает (ущербная она, этакая недоделка от Intel, не ожидал, offload capabilities никаких нет вообще).

saper
()

thttpd 2.25, Internet Explorer и UTF8

Вот такая нездоровая проблема с Internet Explorer: есть страничка, у нее в заголовке указана кодировка KOI8-R, внутри нее есть ссылка, в которой есть KOI8-R русские символы.

Mozilla и Konqueror корректно переходят по ссылке, а Internet Explorer получает ошибку от thttpd, о том, что ссылка не найдена. При этом thttpd указывает ссылку, которая не найдена для Internet Explorer, эта ссылка сформирована в UTF8 почему то.

Т.е. если ссылка была на файл.html, то Internet Explorer запрашивает я└п╟п╧п╩.html.

Я проблему понимаю, но не знаю кто виноват IE или thttpd. С одной стороны страница содержит явное указание KOI8-R, с другой стороны IE в своем пакете в заголовке указывает, что GET идет в кодировке UTF8.

Конфигурационный файл thttpd:
dir=/var/my
chroot
user=myproc
logfile=/var/log/thttpd/thttpd.log
pidfile=/var/run/thttpd/thttpd.pid
globalpasswd
charset=koi8-r
port=80

saper
()

UnixWay: Часто запускаемый бинарник и редко изменяемая конфигурация

Есть некий проект, который хочется сделать Unixway, проект кроссплатформенный, для него недопустимо использование GNU или BSD специфических вызовов или библиотек. Вкратце продукт состоит из бинарника и файла конфигурации.

Бинарник часто запускается (по несколько раз в день), иногда как CGI. Конфигурационный файл - обычный текстовый .conf вида "PARAMETER VALUE", он меняется раз в неделю (в худшем случае) или раз в месяц (в норме).

Парсинг конфигурационного файла в бинарнике длителен и занимает около 2 секунд на целевой машине. Для CGI это не очень хорошо, т.к. бинарник еще и статистику считает некоторое время.

Допускает ли UnixWay такое: - бинарник проверяет контрольную сумму конфигурационного файла, если она не соответствует записанной в бинарном конфигурационном файле, то происходит его перегенерация; - бинарник читает свою конфигурацию из бинарного конфигурационного файла (т.е. уже без парсинга).

Возможно кто то подскажет кроссплатформенную (не GNU/BSD специфичную) библиотеку для парсинга конфигурационного файла?

saper
()

C: int->char[4] для printf/scanf

Очень нужно в программе, обрабатывающей огромное число записей (~2млн.) реализовать быстрое чтение и запись 4 символов. Я вижу самый простой путь - это занести символы в int:
int x;
char *z;
z = (char *)&x;
z[0] = val1;
z[1] = val2;
z[2] = val3;
z[3] = val4;

Вот как теперь, имея этот самый int вывести его через printf ?
printf("%4c", x) или printf("%c%c%c%c", x) не работают

Хочется реализовать именно так, чтобы было быстро. Уточнение насчет x: его возвращает функция, то есть в итоге я хочу получить что то вроде:
printf("%4c", myfunc(x))

В man сказано:
"%c If no l modifier is present, the int argument is converted to an unsigned char". То есть он считывает таки переменную, а не указатель. Как заставить его считать оттуда все 4 байта без конверсии? Если делать %lc, то он читает 2 байта, как я понял, а мне бы 4 :-)

P.S. Я понимаю, что printf/scanf можно переписать или переопределить, но быстро уже не будет :-(

saper
()

RSS подписка на новые темы