По совету анонимуса и других людей осваиваю malloc.
Ниже приведена небольшая тестовая программа. Смысл
ее в том, что в функции init_test(); выделяется
память malloc-ом, там же она первично инициируется
пробным текстом, указатель на эту память при
возврате из функции передается через аргумент главной
программе (main), и далее эта память используется
в главной программе.
Как я понимаю, память выделяется в статической памяти,
а не в стеке. И, стало быть, должна быть доступна и
при возврате в main. Выдача программы, как будто,
подтверждает это:
Вопрос.
Что случится, если во время чтения каталога
(readdir()) этот каталог изменится?
Кто знает прошу ответить.
Пояснение откуда взялся вопрос.
Имеется самодельный копировщик каталога (сырой).
Он рекурсивно обходит дерево и копирует
всё на другой сервер. Использую функцию
readdir(). Каталог большой:
десятки тысяч файлов и общая длина
десятки Гб.
Файлы могут меняться прямо в процессе
копирования (но не слишком часто).
Какой либо синхронизации между копировщиком
и процессами, меняющими файлы, нет.
Но и требования не очень жесткие.
Достаточно скопировать цельный файл, каким он
был до изменения, или после изменения.
Я придумал способ как это сделать.
Просто после первого большого копирования
заново проверить все файлы на дату изменения,
и те, которые менялись с момента начала большого
копирования обработать еще раз. Их таких немного,
и, значит, с ними попроще.
Затем еще раз эти немногие проверить на дату,
и так до полного удовлетворения.
Учитывая не частое изменение файлов, такой
алгоритм можно считать практически конечным.
Я уже было торжествовал победу, но тут сообразил,
что меняться-то могут не только файлы, но и
каталоги. И я не знаю, как поведёт себя функция
readdir() при этом. Пропустить несколько
только что созданных файлов допускается.
Не беда, если файлы скопированы, а вскоре
их удалили.
Но не случится ли тут чего похуже?
Ниже приведена небольшая тестовая программа
на проверку sizeof().
#include <stdio.h>
#include <stdlib.h>
// cd /usr/home/test3test/njx
// gcc test_sizeof.c -o test_sizeof.cgi
// ./test_sizeof.cgi
#define N 6
//--- структура параметров хоста ---
typedef struct {
int port;
char host[100];
} _lin;
//-------------- main --------------
int main()
{
_lin lin[N]; //--- массив структур ---
int k;
k=funk_1(lin);
printf("k=%d\n",k);
exit(0);
}
//-------------- funk_1 --------------
int funk_1(_lin lin[]){
int k;
k=funk_2(lin);
return(k);
}
//-------------- funk_2 --------------
int funk_2(_lin lin[]){
int k;
k=sizeof(lin[0].host);
// k=sizeof(_lin.host);
// k=sizeof(_lin);
return(k);
}
Во вложенные функции передается массив lin[ ],
вернее указатель на него.
Выдача этой программы
k=100
т. е. длина массива host.
Мне как раз и нужно в нижней вложенной
функции funk_2() получить длину этого массива.
Там ещё есть закомментированная строка, которую
я тоже попробовал, но с ней не компилится.
Вопрос.
Случайность ли это или правило?
Не скомпилирует ли другой «правильный» компилятор
по другому?
Имеется файл строк, каждая строка это отдельная запись БД.
Нужно сделать транзакцию - изменить одну из этих строк.
При этом длина строки не меняется.
Должно выдерживать мягкий сбой (выключение питания).
Винт плохой и при сбое портит весь сектор (или иную минимальную порцию данных).
Значит я должен в журнале сохранить всё то, что может быть испорчено,
т. е. сектор (или секторы) содержащий эту строку.
Вопрос 1.
О длине сектора.
Как узнать длину сектора или иной порции данных,
которая может быть испорчена?
Вопрос 2.
Что если я буду для верности сохранять заведомо
большую порцию, а именнно 8 Кбайт, начало порции
кратно ей самой от начала файла.
Хотелось бы написать простую специализированную
базу данных.
Под специализированной понимается:
не универсальная, для конкретного приложения.
Отсюда и ожидаемая простота.
Много чего не понимаю. Вот первая тестовая задача:
Задача 1.
Имеется файл-счетчик count.txt малой длины (100 байт).
и некая программа, время от времени наращивающая
этот счетчик.
Требуется: переделать так, чтобы при мягком сбое (отключение питания)
не потерять счетчик.
Думал - думал и ничего лучше не придумал,
кроме следующего.
Создаю два равнозначных файла-счетчика,
дублирующих друг друга.
count_1.txt
count_2.txt
Формат файла такой
count=4; st_tr=36; ks=123345
где
count=4; -основной счетчик;
st_tr=36; -вспомогательный кольцевой счетчик наращиваний,
например, после 99 следующее число 0;
ks=123345 -контрольная сумма.
Наращивание делать так:
-читаем каждый из этих файлов, проверяем контрольные суммы
и совпадение данных в обоих файлах;
Далее по одной из четырех ветвей
-если все в порядке, то изменяем данные и перезаписываем
эти два файла. Дождать, когда они окажутся на диске. Вот и всё.
-если файлы отличаются, и в одном из них правильная ks,
то восстановить, т. е. скопировать правильный в не правильный,
дождать, когда он
окажется на диске (как проверить - не ведомо), затем
нарастить счетчики в обоих файлах.
-если файлы отличаются, и в каждом правильная ks, лучшим из них
считать тот, у которого больше (по кольцу) вспомогательный
счетчик, сделать восстановление, затем нарастить оба.
-другие варианты считать не подлежащими восстановлению.
Продолжение темы.
На странице 811 был вопрос о select
и о разрешении имен хостов без подвисания.
Anonymous посоветовал libasyncns,
и я написал там, что все в порядке.
Я погорячился.
Мало того что сложно, так еще, как я понял,
там создается дополнительный процесс
для каждого запроса.
А это противоречит намерениям.
И мыслится подходящим делать прямые запросы
сервера DNS (из тех, что в файле /etc/resolv.conf)
через UDP-сокеты и подключать эти запросы
к центральному select-у.
Трудно только распарсить ответы DNS,
кроме самых простых.
Нет хорошего описания форматов ответов.
Пользуюсь пока этим: http://www.crossplatform.ru/documentation/tcp_ip/glava14.php
но здесь не доходчивое и не исчерпывающее.
Пытаюсь написать простой малопроцессный
сервер (однонитевой).
Малопроцессный подразумевает:
один процесс сервера обслуживает несколько клиентов.
Использую TCP-сокеты и select.
Select занимает центральное место, а все
остальное к нему прилажено.
Все функции сокетов, pipe-каналов и файлов
хорошо прилаживаются к select.
Но потребовалось разрешать имена хостов
в ip-адреса, а функция
hp=gethostbyname(serv_name);
которой я раньше пользовался,
не прилаживается.
Существует ли какой-нибудь способ
разрешения имен хостов не подвисая.
При его перезапуске система не сразу
освобождает адрес локальной привязки сокета.
Вследствие этого ошибка вызова bind().
Порой не удается вновь запустить сервер
несколько минут.
Можно с этим смириться, но всё же неудобство.
Имеется сервер (самодельный).
При переносе на другую машину возникла трудность.
(FreeBSD 6.3-RC2 --> FreeBSD 7.2-RELEASE (GENERIC))
Требуется избавиться от переменных окружения
для того, что бы сформировать новые и передать их
execl-ом другим программам.
Использую функции
void unsetenv(const char *name);
int setenv(const char *имя, const char *значение, int overwrite);
Имеются «клиент» и «сервер» (самодельные).
Работают поверх TCP.
Фрагмент клиента:
//--- sd_client -сокет, соединенный с сервером ---
k=read(sd_client, buf, sizeof(buf));
Конец фрагмента.
Сервер на запрос клиента посылает данные,
а затем закрывает сокет close(sd_serv) на своей стороне.
При закрытом на сервере сокете (sd_serv),
на стороне клиента вызов read()
возвращает 0, и это признак конца передачи.
В штатном режиме это работает.
Но на сервере иногда случаются ошибки (не доступны
все или часть данных).
Вопрос.
Возможно ли на стороне сервера
так подействовать на сокет (sd_serv),
что бы на стороне клиента вызов read()
вернул бы -1.
Нужно прервать процесс, ожидающий блокировку файла.
Процесс, ожидающий блокировку файла,
получает сигнал и почти не реагирует на этот сигнал.
Не могу понять почему.
(Функция printf() запрещена в обработчиках сигналов,
но поскольку программа простая тестовая и от безысходности)
(состояние процессов удобно смотреть в другом окне утилитой top)
Эта программа не работает так, как я ожидал.
Ожидалось:
0 сек. -запуск программы, процесс (pid>0) блокирует файл;
5 сек. -процесс (pid==0) запрашивает блокировку файла и ждет её;
15 сек. -процесс (pid==0) получает сигнал, ожидание блокировки
прерывается. Вызов k=fcntl(fd,F_SETLKW,&lock); возвращает -1;
На самом деле работает так:
0 сек. -запуск программы, процесс (pid>0) блокирует файл;
5 сек. -процесс (pid==0) запрашивает блокировку файла и ждет её;
15 сек. -процесс (pid==0) прерывается сигналом
(обработчик пишет слово signal), и снова,
как ни в чем не бывало дожидает блокировку.
Дождавшись получает её.
fd -объявлен глобальным потому, что если раскомментировать строку
//close(fd);
в обработчике, то это выход из положения.
Хотелось бы понять почему не работает как задумано.
Кто знает прошу ответить.
Машина имеет несколько ip-адресов.
Прием запросов со всех имеющихся ip-адресов.
Вопрос: возможно ли узнать на какой ip-адрес
из них пришел запрос клиента?