LINUX.ORG.RU

Сообщения oleg_2

 

[СИ] close и сигнал.

Форум — Development

[СИ] close и сигнал.

Язык СИ
ОС UNIX

Кусок кода:


start:
      ....

    k=close(fd);
    if(k<0) goto ERR; //--- close() может быть прерван SIGALRM ---
    fd=-1;
      ....
    goto start;

ERR:

    alarm(0);  // выключить сигнал
    if(fd>=0) close(fd);
    fd=-1;
    goto start;

Т. к. процесс бесконечный, то файл обязательно нужно закрыть.
Я догадываюсь, что если close() обрамить масками сигнала, то было бы хорошо.
Сработает ли это повторное закрытие?
Или непременно маски сигнала в главной ветке?

Можно расширить вопрос. Если close возвращает ошибку, любую,
то как избавиться от файла?

 

oleg_2
()

Ввод-вывод. fgetc, getc, fileno.

Форум — Development

[СИ] Ввод-вывод. fgetc, getc, fileno.

Язык СИ
ОС UNIX

Вопрос-1.
В каких случаях следует или не следует применять getc вместо fgetc?

Например, СИ-функция общего назначения, т. е. заранее неизвестно где она
будет применяться - возможно в много-потоковой, или иной программе
с особенностями.
Предполагается чтение файла библиотечными getc (или fgetc), fread, rewind.
Быстродействие желательно. В чем опасность getc, что она выделена отдельно?

Вопрос-2.
Есть СИ-функция, в которую передается fd, и которая читает файл read(fd).
А нужна такая же, но чтоб фигурировал аргумент fp, а не fd.
Переделать ее на бибиотечную fread() трудно, и будет двойное
буферирование.
Для нее я сделал обертку, т. к. файл открывается функцией fopen().
Ниже приведена схема.


int fun(int fd)
{
    int k;
    k=read(fd);
    if(k<0) return(-1);
    // обработка файла
    return(0);
}

int obertka_fun(FILE *fp)
{
    int fd, k;
    fd=fileno(fp);
    k=fun(fd);
    return(k);
}

int main()
{
    FILE *fp=NULL;
    int k;
    // этот цикл символизирует бесконечность процесса
    while(1){
        // получить имя файла
        fp=fopen(fname, "r");
        if(fp==NULL) continue;
        k=obertka_fun(fp);
        fclose(fp);
    }
    exit(0);
}

В чем тут опасность? Осталось ли что-нибудь незакрыто?

Кто знает прошу ответить.

oleg_2
()

[СИ] JPEG. Прогрессивное кодирование.

Форум — Development

[СИ] JPEG. Прогрессивное кодирование.

Язык СИ
ОС UNIX

Написал простые декодер, кодер JPEG.
Теперь пытаюсь написать простой прогрессивный JPEG-декодер.
Есть два вида прогрессивного кодирования:
-спектральный (spectral selection);
-битовый (successive approximation).

Спектральный я написал, есть только один пробный файл, работает.
Вот пример:
http://90.156.197.181:8282/primer2.html
http://90.156.197.181:8282/primer3.html

Битовый не получается (вторая ссылка).
У меня есть только два пробных битовых файла, большие.
Берет только первый скан (кодовый блок).
На втором выдает ошибку, а вроде бы должен быть закодирован
так же, как спектральный.
До следующих сканов, которые должны кодироваться по другому,
пока не добрался вовсе, и не могу разобраться теоретически.
Изучаю по этому материалу:
http://www.w3.org/Graphics/JPEG/itu-t81.pdf

Мне нечем закодировать тестовые прогрессивные файлы.
Если у кого есть мощное графическое приложение,
прошу закодировать несколько файлов.
Мне нужны битовые (successive approximation) тестовые файлы.
Пригодятся и spectral selection.
Вот файлы:
http://90.156.197.181:8282/primer1.html
Или с этой просьбой надо в другой раздел?


 

oleg_2
()

[СИ] Объявление и определение переменных.

Форум — Development

[СИ] Объявление и определение переменных.

Язык СИ
ОС UNIX

Иногда в СИ-программах встречается такое:


typedef struct node node;
typedef char type;
typedef node *tree;

struct node {
    int   w;
    type  val;
    node  *left;
    node  *right;
};

И это компилится и работает.
Я не понимаю таких строк. Я бы написал так:


typedef char type;

struct node {
    int   w;
    type  val;
    node  *left;
    node  *right;
};

typedef struct node node;
typedef node *tree;

Вот когда компилятор читает строку «typedef struct node node»,
то что он должен думать? Ведь node описан ниже по тексту.
Для сравнения два определения функций:

int get_matr_1(int w, int h, char matr[][w]) {...}
int get_matr_2(char matr[][w], int w, int h) {...}

Первая компилится и работает. Вторая не компилится. Видимо потому,
что w после matr[][w].
Про незавершенные структуры читал в учебнике и даже сам пользовался.
Но тут-то другое.
Какое тут правило?

 

oleg_2
()

[СИ] Стандартный ввод-вывод и автозапуск.

Форум — Development

[СИ] Стандартный ввод-вывод и автозапуск.

Язык СИ ОС UNIX

Имеется маленькая стартовая программа предназначенная для авто-запуска
демонов при перезагрузке системы. Сама эта программа запускается
автоматически штатно (FReeBSD /usr/local/etc/rc.d/start.sh).

В обычных программах - не демонах, или демонах запущенных вручную, сначала
есть ввод-вывод. В программы-демоны я включаю такой кусок кода:
close(0);
close(1);
close(2);
При ручном запуске это помогает.
А как при автоматическом? Первое, что приходит в голову - должны бы быть
все три, направленные в никуда, для совместимости.


    Схема
    
программа "старт" (запускается вручную (для теста) или автоматически).
      ....
    if(pid==0){
        k=chdir("демон");
        execle("демон", argv, envp);
        exit(0);
    }
      ....
    
    
программа "демон" (запускается вручную, или автоматически программой "старт").
      ....
    fd=open("file");
      ....
    close(0);
    close(1);
    close(2);
      ....
    fd - должен остаться открытым.

Вопрос-1.
Есть ли у этой стартовой программы ввод-вывод, и если да,
то куда он направлен, и можно ли смело применить close, fclose в демонах?

Вопрос-2.
В демонах есть printf(«Text»); и т. п., которые полезны при ручном запуске
вплоть до демонизации. Куда денутся эти сообщения при автозапуске? Не повредят ли?

Вопрос-3.
Правильный ли close(0); и др., или правильнее опасный fclose(stdin); ?

 

oleg_2
()

[СИ] Как узнать кодировку локали.

Форум — Development

[СИ] Как узнать кодировку локали.

Язык СИ
ОС UNIX

Имеется самодельная СИ-программа. Она предназначена для работы
на машине-сервере в Дата-центре. Запускается через PuTTY.
Выдача программы должна быть на русском языке. Но ничего не
переключать вне этой программы.
В исходнике кодировка windows-1251. В программе есть перекодировщики
на koi8-r, utf-8.

На моем сервере и еще на двух других
опробована, там кодировка koi8-r. Работает, но я пока жестко
задал перекодировщик. Я слыхал, что некоторые работают на
других кодировках.

Вопрос-1.
Правильно ли я понимаю, что когда я подключаюсь через PuTTY,
то это моя локаль?

Вопрос-2.
Существует ли способ, чтоб программа узнала, какую кодировку
лучше выдать?

Кто знает прошу ответить.

 

oleg_2
()

[СИ] Куда-то пропала блокировка fcntl.

Форум — Development

[СИ] Куда-то пропала блокировка fcntl.

Язык СИ
ОС UNIX (FreeBSD 7.2)

При запуске самодельного сервера на pid-файл ставится
блокировка fcntl, как описано в книге Стивенса
«UNIX взаимодействие процессов» (9.7 Запуск еднственного
экземпляра демона. стр.233).
Когда потребовалось остановить сервер, то пусковой модуль
отказывался посылать сигналы. Это если pid-файл не заблокирован,
то он думает, что сервер не запущен.
По top-у и номеру из pid-файла, а так же по работе сервера,
было видно, что мастер-процесс, который и держит блокировку,
работает. При запуске обработка ошибки fcntl есть.
За период работы никаких происшествий на машине-сервере не было.

Вопрос-1.
Куда могла деться? Кто-нибудь сталкивался или знает?

Вопрос-2.
В программе сигналы посылает вызов
kill(-pid, SIGINT);
Отрицательный -pid посылает сигналы всем процессам группы процессов.
Есть ли похожая команда sh?

Вопрос-3.
Если процесс - лидер группы процессов кончился, то сработает ли
kill(-pid, SIGINT); - Группа-то ведь осталась? Конечно, надо
протестить, потом. А сейчас если кто знает готовый ответ?

Кто знает прошу ответить.

 

oleg_2
()

[СИ] Как работать с off_t числами.

Форум — Development

[СИ] Как работать с off_t числами.

Язык СИ
ОС UNIX

Не знаю штатных средств работы с off_t числами, надежных.
Ниже две самодельных функции для преобразования
off_t -> строка и обратно.

Вопрос-1.
Существуют ли надежные штатные средства?

Вопрос-2.
В функции my_ato_off() (см. ниже) не знаю, как правильно
отловить выход из диапазона. Там есть закомментированная
строка, которая предположительно может отловить ошибку.
И при опробовании да, отлавливает. Но всегда ли, при
любой ли строке символов?

Кто знает прошу ответить.



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

//   gcc forum_off_t.c -o forum_off_t.cgi
//   ./forum_off_t.cgi

//------------------- my_ato_off ---------------------
off_t
my_ato_off(const char *buf)

{
    off_t  s, sm;
    const char *p1;
    int sig=0;

    p1=buf;
    while(*p1==' ') p1++;
    if(*p1=='-'){ sig=1; p1++;}
    s=0;
    while(*p1>='0' && *p1<='9'){
        sm=(s*10)+((*p1)-'0');
        //if(sm<s) return(-1);
        s=sm;
        p1++;
    }
    if(sig>0) s=-s;
    return(s);
}

//----------------- my_off_toa -------------------------

int my_off_toa(off_t  d, char *str, int Sstr)

{
    char *p1, buf[30];
    int  k, sig=0;

    p1=buf;
    if(d<0) sig=1;
    if(sig==0) do{ k=d%10; *p1++=('0'+k);} while((d=d/10)!=0);
    else do{ k=d%10; *p1++=('0'-k);} while((d=d/10)!=0);

    if((p1-buf)>=(Sstr-sig)){ *str=0; return(-1);}
    if(sig>0) *str++ = '-';
    while(p1>buf){ *str++ = *(--p1);}
    *str=0;

    return(0);
}

//--------------- main ---------------

int main()

{
    char *p, buf[100], str[21];
    off_t  s;
    int    k;

    printf("\n---------------------------------------\n");

    while(1){
        p=fgets(buf, sizeof(buf), stdin);
        if(p==NULL){
            printf("p==NULL\n");
            printf("\n---------------------------------------\n");
            continue;
        }
        printf("1. buf=%s\n", buf);

        s=my_ato_off(buf);
        printf("2. s  =%lld\n", s);

        k=my_off_toa(s, str, sizeof(str));
        printf("3. str=%s; (%d)\n", str, k);

        k=atoi(buf);
        printf("4. k  =%d\n", k);
        printf("\n---------------------------------------\n");
    }
    exit(0);
}



 

oleg_2
()

[СИ] Как задать off_t константу.

Форум — Development

[СИ] Как задать off_t константу.

Язык СИ
ОС UNIX

Как задать off_t константу
off_t offmax=0x7FFFFFFFFFFFFFFF;
Компилятор не принимает.
Пробовал так:

off_t k1, k2;
k1=0x7FFFFFFF;
k2=0xFFFFFFFF;
offmax=((k1<<32)& (~k2)) + k2;

Получилось.
А можно ли компактнее и вернее?
Примерно так
offmax=OFFMAX;
какая уж есть в действительности - 32 или 64.

Кто знает прошу ответить.

 

oleg_2
()

[СИ] Заполнен диск. Пропали файлы.

Форум — Development

[СИ] Заполнен диск. Пропали файлы.

Ясык СИ
ОС UNIX

Случилось заполнение диска. Не стали записываться файлы.
Пришел админ, разгреб завалы, и заработало как раньше.

Но из-за этого сбоя пропали файлы. Как я догадался, причина
в том, что в некоторых программах есть проверка открытия файла,
но нет проверки записи. А в других программах сначала опустошается
старый файл, а потом записывает новое содержимое. Это тоже
не работает. Казалось бы место только что освободилось. Но нет.
Это было видно по FTP. Удалить файлы - да. Записать другие - нет.
По этой причине не удалось запустить небольшую, наспех написанную
тестовую программу записи.

Заполнение диска - случай редкий. Но можно ли как-то от этого
застраховаться?

Вопрос-1.
Если диск заполнен так, что больше не пишет, то всегда ли вызов
k=write();
будет возвращать ошибку? Система пишет не сразу на диск, а в свой
буфер. Не случится ли так, что в буфер запишет без ошибки, а на
диск не запишет?

Вопрос-2.
Файлы ошибок тоже не будет писать. А хотелось бы чтоб писало.
Как быть?

Вопрос-3.
Сработает ли такое: некоторым особо важным файлам установить
стандартную длину (1 кБ), и никогда их не опустошать, писать
весь буфер на старое место?

Кто знает прошу ответить.

 

oleg_2
()

[СИ] Протокол HTTPS.

Форум — Development

[СИ] Протокол HTTPS.

Язык СИ
ОС UNIX

Пытаюсь изучить HTTPS.
http://www.ietf.org/rfc/rfc2246.txt (TLS версия 1.0)
http://citforum.ru/nets/semenov/6/tls.shtml -TLS русский перевод
http://citforum.ru/nets/semenov/6/ssl_65.shtml -SSL русский

На стадии client-hello/server-hello.
Вижу их.
Начинаю понимать описанные в протоколах TLS и SSL структуры,
но путаница в голове великая.
Особенно со слоями и версиями.

Почему-то ИЕ дает client-hello соответствующий SSL.
А когда я такой же client-hello даю на серверы, то
ответ server-hello соответствует TLS.
Не понимаю как различить где TLS, а где SSL?
Ведь в TLS есть свой client-hello (с ним не работает).
Чем руководствоваться практически?

Кто знает прошу ответить.

 

oleg_2
()

[СИ] mmap-массив и синхронизация.

Форум — Development

[СИ] mmap-массив и синхронизация.

Ясык СИ
ОС UNIX

Фрагмент кода:


    //--- родительский процесс - только читает arr[] ---

      ....
    arr=(int*)mmap(NULL, sizeof(int)*ARRSIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0);
      ....
    while(1){
		  ....
        n0=0;
        i=0;
        while(i < n){  //--- n <= ARRSIZE ---
            if(arr[i]==0) n0++;
            i++;
        }
          ....
    }

    //--- дочерний процесс ---
    //--- имеет уникальный номер i, соответствующий индексу arr[] ---

start:
      ....
    arr[i]=1;
      ....
    arr[i]=0;
      ....
    goto start;

Родительский процесс (мастер-процесс) периодически читает
arr[] на предмет подсчета свободных рабочих процессов пула.
Никогда не пишет туда.
Рабочие процессы пишут в arr[] свободен-занят, каждый под
своим индексом.
Без какой-либо синхронизации.
Почему без синхронизации?
Здесь и сейчас для упрощения.
Там и потом по другим причинам.

По простоте я понимаю так.
Запись одного элемента не должна бы влиять на другие элементы.
А если чтение точно совпадет с записью, то будет прочитан ноль
или не ноль. И то и другое правильно. Микросекунды не в счет.
Предполагаю так же, что перебивка чтением-записью не испортит запись.

Тест проходит хорошо. Везение. А как на самом деле?

Кто знает прошу ответить.

 

oleg_2
()

[СИ] Простой HTTP-сервер.

Форум — Development

[СИ] Простой HTTP-сервер.

Язык СИ
ОС UNIX

Имеется простой самодельный HTTP-сервр с пулом
рабочих процессов (каждому клиенту свой процесс).
Он якобы работает, но есть сомнения.

По замыслу рабочий процесс сервера должен
позаботиться, чтоб запущенный им CGI-скрипт
кончился в пределах тайм-аута, а то послать
CGI-скрипту SIGKILL.

Ниже приведена схема рабочего процесса с
куском доподлинного нового кода.


//--- глобальные ---
int volatile fl_alarm=0;
pid_t  pid1;

void timer(int n)
{
    kill(pid1, 9);  //--- сигнал CGI-скрипту ---
    fl_alarm=1;
    return;
}

    //--- СХЕМА РАБОЧЕГО ПРОЦЕССА ---

start:
    sd=accept();

k_alive:
    k=read(sd);      //--- ждем запрос (с тайм-аутом) ---
    pid1=fork();

    //--- дочерний процесс -> CGI-скрипт ---
    if(pid1==0){
        close(sd);
        execl();
        exit(0);
    }

    //--- родительский процесс ---
    signal(SIGALRM, timer);
    alarm(tm_out);   //--- общий тайм-аут запроса ---
    k=read(sd);      //--- POST-запрос клиента (с тайм-аутом) ---
    k=write(pipe0);  //--- на ввод CGI (блокирующий) ---
    k=read(pipe1);   //--- с вывода CGI (блокирующий) ---
    k=write(sd);     //--- ответ клиенту (с тайм-аутом) ---

    //--- ДОПОДЛИННЫЙ КОД ---
    tm=alarm(0);
    if(fl_alarm>0){
        pid3=wait(&status);  //--- борьба с зомби, блокирующий ---
        fl_alarm = 0;
    }
    else{
        pid3=-1;
        tm1=0;
        while(tm1 < tm){
            pid3=waitpid(pid1, &status, WNOHANG);   //--- неблокирующий ---
            if(pid3>0) break;
            sleep(TM);  //--- TM -период опроса 1 сек. ---
            tm1=tm1 + TM;
        }
        if(pid3<=0){
            kill(pid1, 9);
            pid=wait(&status);   //--- блокирующий ---
        }
    }
    //--- КОНЕЦ ДОПОДЛИННОГО КОДА ---

    if(fl_aliv > 0) goto k_alive;
    close(sd);
    goto start;

1.
kill() в обработчике сомнителен.
Я не вижу иного способа вынести его оттуда,
кроме как сделать чтение/запись в pipe-канал
с тайм-аутом подобно сокету. Иначе можно зависнуть
на read(pipe), если CGI-скрипт, например, зациклится.
Или даже все три (сокет, ввод и вывод скрипта) завести
на центральный select процесса, время вычислять, и
совсем отказаться от сигнала SIGALRM.
Это, наверно, возможно. Но простой поначалу сервер
всё больше утяжеляется.

2.
Глобальный, фигурирующий в обработчике сигнала
pid_t pid1;
Как его и можно ли правильно определить? volatile?
В статье http://www.opennet.ru/base/dev/unix_signals.txt.html
написано
«Правило 3

Существует ровно один тип статических данных, sig_atomic_t, переменную
которого может установить обработчик асинхронного сигнала. Поведение
приложения не определено, если асинхронно вызванный обработчик
обращается к статическим данным любым другим способом.»

В этой статье, однако, есть противоречия.

3.
Цикл опроса waitpid().
А как по другому?
alarm() уже выключен. Нужно выдержать тайм-аут.
В других местах вызываем wait() в расчете
на то, что SIGKILL сделает свое дело.
Если код заменить на этот (старый):

    //--- ДОПОДЛИННЫЙ КОД ---

    pid3=wait(&status);  //--- борьба с зомби, блокирующий ---
    //--- здесь сработает обработчик и пошлет сигнал другому процессу ---
    tm=alarm(0);
    fl_alarm = 0;

    //--- КОНЕЦ ДОПОДЛИННОГО КОДА ---

то есть опасность прибить ни в чем неповинный процесс.

Получается, что теоретически сервер работать не может.

Как сделать правильно?

Кто знает прошу ответить.

 

oleg_2
()

[СИ] Стивенс. «UNIX: разработка сетевых приложений».

Форум — Development

[СИ] Стивенс. «UNIX: разработка сетевых приложений».

Язык СИ
ОС UNIX

Хотел прочитать книгу Стивенса (русскую)
«UNIX: разработка сетевых приложений».
Скачал по ссылке
http://reslib.com/book/UNIX_razrabotka_setevih_prilozhenij
Плохо. Мало того, что вместо текста - рисунок, так еще крайне
неудобно листать и прокручивать страницы.

Есть же хорошая HTML-книга
http://www.e-reading.org.ua/bookreader.php/148368/Stivens_-_UNIX%3A_vzaimodei...
«Уильям Стивенс UNIX: взаимодействие процессов МАСТЕР-КЛАСС».

А существует ли такая же удобная русская
«UNIX: разработка сетевых приложений»?

Интересуют так же другие книги Стивенса
русские, бесплатные в удобном виде.

Кто знает прошу ответить.

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

 

oleg_2
()

[СИ] HTTP-протокол.

Форум — Development

[СИ] HTTP-протокол.

Язык СИ
ОС UNIX

Вопрос не сиюминутный, но хотелось бы знать.

Имеется простой самодельный HTTP-сервер.

Может ли клиент послать запрос блоками (chunked)?
В той части rfc, которую я осилил, не возбраняется.
Довелось читать статью Сысоева про уязвимость сервера
при приеме chunk-запросов. Видимо можно.

Если так, то как тогда соотносятся chunk-запрос и
поле Content-Length, которому rfc предписано быть
в запросе для совместимости?

Мои фирменные клиенты (ИЕ, Мозила-Файфокс, Опера)
дают простые запросы, не chunk. Посмотреть негде.

Кто знает прошу ответить.

 

oleg_2
()

[СИ] Убойный SIGPIPE.

Форум — Development

[СИ] Убойный SIGPIPE.

Язык СИ
ОС UNIX

Опасна ли такая конструкция (код урезан, но главное осталось):


int get()

{
    signal(SIGPIPE, SIG_IGN);
    
    sd=make_sd();   //--- создает приконнекченный  TCP-сокет ---
    k=write(sd);
    if(k < 0) goto RET;
    k=read(sd);

RET:
    close(sd);
    signal(SIGPIPE, SIG_DFL);
    return();
}

Руководитель потребовал, чтобы при возврате из функции
установить исходную, т. е. дефолтную реакцию на SIGPIPE.
Но при этом должны действовать какие-нибудь другие SIGPIPE,
но только не тот, который от этого сокета.

Опасно ли?
Первое, что приходит в голову - да, опасно.
Сигнал распространяется не мгновенно, и придет после
установки SIG_DFL.

Так ли это?
Если да, то как поступить?

Кто знает прошу ответить.

 

oleg_2
()

[СИ] Прервать процесс.

Форум — Development

[СИ] Прервать процесс.

Язык СИ ОС UNIX

Требуется прервать процесс, подвисший на блокировке файла fcntl.
Имеется кусок кода:


   int volatile fl_int = 0;
   int volatile fd_int = -1;


void sigint(int n)
{
    close(fd_int);
    fl_int=1;
    return;
}

      ....
      
    signal(SIGINT, sigint);
    sigprocmask(SIG_SETMASK, &mask2, NULL);   //--- блокирует SIGINT ---

      ....
      
    fd_int=fd;
    sigprocmask(SIG_SETMASK, &mask1, NULL);   //--- разблокирует SIGINT ---
    k=my_lock(fd, F_WRLCK);                   //--- блокировка файла fcntl ---
    sigprocmask(SIG_SETMASK, &mask2, NULL);   //--- блокирует SIGINT ---
    fd_int=-1;
    if(fl_int > 0){ fd=-1; return(-1);}
    
      ....

При опробовании это работает. Но при опробовании много чего
работает. А будет ли это работать всегда? Я имею в виду вызов
close() в обработчике сигналов. Вынести его из обработчика
(с использованием sigaction и сброшенным флагом SA_RESTART)
плохо тем, что сигнал может придти между разблокированием
сигнала и блокировкой файла. И я безнадежно зависну
на блокировке файла.

В книге Стивенса
«UNIX взимодействие процессов» в таблице 5.1 приведен список
функций, допустимых в обработчике по POSIX. В этот список
функция close() входит. Там же в примечании к этой таблице
указаны функции по ANSI C и UNIX 98. close() там нет.

Чем руководствоваться практически? Или есть ли другие способы
обойти эту двусмысленность?

Кто знает прошу ответить.

 

oleg_2
()

[СИ] malloc.

Форум — Development

[СИ] malloc.

Язык СИ
ОС UNIX

Осваиваю malloc.

Действительно, чего я его боялся? По утечке памяти.

Я, бывало, спотыкался на незакрытии файлов в не разовых процессах
(демонах). Но теперь немало преуспел в деле закрытия файлов.
И это умение легко перенести на malloc.

Вопрос-1.
Если я в некоторой функции определю переменную так
static char buf[100];
то когда под нее будет выделена память - сразу при
запуске программы, или при первом вызове функции?
И можно ли такую функцию использовать рекурсивно?
Как я понимаю, нельзя.

Вопрос-2.
Выделяет ли malloc() память побайтно или страницами?
Если страницами, то неэкономично для маленьких переменных.
Если побайтно, то трудно представить, как тогда работает realloc.
В книге Стивенса описан mmap, а не malloc. Но я подозреваю,
что они родственные.

Кто знает прошу ответить.

 

oleg_2
()

[СИ] HTTP/1.1. Chunked

Форум — Development

[СИ] HTTP/1.1. Chunked

Язык СИ
ОС UNIX

Помогите разобраться.

Вот выдержки из rfc2616
http://www.ietf.org/rfc/rfc2616

Пункт 3.6.1
       Chunked-Body   = *chunk
                        last-chunk
                        trailer
                        CRLF

       chunk          = chunk-size [ chunk-extension ] CRLF
                        chunk-data CRLF
       chunk-size     = 1*HEX
       last-chunk     = 1*("0") [ chunk-extension ] CRLF

       chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
       chunk-ext-name = token
       chunk-ext-val  = token | quoted-string
       chunk-data     = chunk-size(OCTET)
       trailer        = *(entity-header CRLF)

----------------------------------------------

Пункт 7.1

       entity-header  = Allow                    ; Section 14.7
                      | Content-Encoding         ; Section 14.11
                      | Content-Language         ; Section 14.12
                      | Content-Length           ; Section 14.13
                      | Content-Location         ; Section 14.14
                      | Content-MD5              ; Section 14.15
                      | Content-Range            ; Section 14.16
                      | Content-Type             ; Section 14.17
                      | Expires                  ; Section 14.21
                      | Last-Modified            ; Section 14.29
                      | extension-header

       extension-header = message-header

----------------------------------------------

Пункт 4.2

       message-header = field-name ":" [ field-value ]
       field-name     = token
       field-value    = *( field-content | LWS )
       field-content  = <the OCTETs making up the field-value
                        and consisting of either *TEXT or combinations
                        of token, separators, and quoted-string>

Пытаюсь написать простой HTTP-клиент.
Для написания и теста парсеров заголовков нужны «максимальные» заголовки,
т. е. наиболее неудобные для парсения.
А получаю только «минимальные», простецкие.
Вот сам написал для теста файл.

HTTP/1.1 200 OK
Set-Cookie: yandexuid=1140701277744450; path=/; domain=.yandex.ru
X-Robot-status: off
transfer-encoding: chunked
Content-Type:
	text/html;
	charset=windows-1251
My-Var: Proba

8
data-1 ;
 8; eda=kolbasa
data-2 ;
8
data-3 ;
0; file=nul
name1:  id64;
	id65
name2:
	id76
	konec

В конце пустая строка («\r\n\r\n»).
Чистое тело «data-1 ;data-2 ;data-3 ;»

Вопрос-1.
Правильно ли я понял, что заголовок блока данных (chunked) всегда
одна-единственная строка, и, значит, перенос строки - это верный признак
конца заголовка блока. Как в примере:
" 8; eda=kolbasa"
«0; file=nul»

Вопрос-2.
Правильно ли я понял, что последний нулевой блок может содержать
завершающую запись (trailer), которая подобна обычному верхнему
HTTP-заголовку (а не что-нибудь другое), и, значит, парсить ее
нужно подобным способом?

Кто знает прошу ответить.

 

oleg_2
()

[СИ] Стивенс. Не понимаю.

Форум — Development

[СИ] Стивенс. Не понимаю.

Язык СИ ОС UNIX

В книге «UNIX Взаимодействие процессов»
(русская, бумажная) приведена
упрощенная реализация очередей сообщений POSIX.
Параграф 5.8. Там используется контрольное число
MQI_MAGIC, определенное define-ом. Вот оно-то и
не понятно. Вот фрагменты этих функций:


Листинги 5.17 - 5.19.

7   mymqd_t
8   mymq_open(const char *pathname, int oflag, ...)
9   {
          ....
64          /* Выделение структуры mymq_info{ } для очереди */
65      if( (mqinfo = malloc(sizeof(struct mymq_hdr))) == NULL)
66          goto err;
67      mqinfo->mqi_hdr = mqhdr = (struct mymq_hdr *) mptr;
68      mqinfo->mqi_magic = MQI_MAGIC;
          ....
107     return((mymqd_t) mqinfo);
159 }


Листинг 5.20.

3   int
4   mymq_close(mymqd_t mqd)
5   {
	      ....
11      if(mqinfo->mqi_magic != MQI_MAGIC){
12          errno = EBADF;
13          return(-1);
14      }
          ....
24      mqinfo->mqi_magic = 0;   /* на всякий случай */
25      free(mqinfo);
26      return(0);
27  }

В функции mymq_open(); инициируется поле magic, а
во всех других функциях есть проверка, как в mymq_close();
То, что структура выделяется malloc-ом, я понимаю
так: структура должна существовать и при возврате
из mymq_open(), значит, локальная не годится.
Ну а что-же magic? От него-то какая польза?
Я думал, что это защита от ошибок программиста,
чтоб процесс не падал.
Но когда разобрался, то ничего не понял.
Я не тестил, теоретически разбирался.
Процессы не родственные (а хоть бы и родственные),
однопотоковые. Если всё написать правильно, то и без
magic все сработает хорошо. А если допустить ошибку,
то всё равно не поможет. Например, забыл написать
mqd = mymq_open(); и вызываю другие функции очереди.
Падение. Ошибочно дважды вызвал mymq_close(); Опять
падение. Ведь первый mymq_close(); освободит память,
а второй уже полезет в никуда (память-то уже освобождена).

В чем тут дело?

Кто знает прошу ответить.

 

oleg_2
()

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