LINUX.ORG.RU
Ответ на: комментарий от anonymous

Успокойся)) Он же не программист) Все на лоре знаю что он верьма религиозен) Не стоит это путать с программированием) У него своя религия - Единого (Единственного?) Си :)

Noob_Linux ★★★★
()
Ответ на: комментарий от Eddy_Em

И как ты предлагаешь его обработать? Завести глобальные структуры данных, в которых хранит результаты чтения/записи и индикацию того, что мы свалилилсь именно на чтении/записи из замапленного файла? Ты совсем поехавший?

kirk_johnson ★☆
()
Ответ на: комментарий от Eddy_Em

А то ты не получишь какую-нибудь гадость с fopen!

В fopen(3) я не вижу упоминания сигналов. А в mmap(2) ещё как.

kirk_johnson ★☆
()

Удобный API. Переносимость на не-POSIX платформы.

Legioner ★★★★★
()

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

Специально задание для Eddy_Em и true_admin: реализовать

char* fdgets(char *buf, int size, int fd)
поверх «обычных файловых дескрипторов».

kawaii_neko ★★★★
()
Ответ на: комментарий от kawaii_neko

А в чем проблема-то?

Читаем сразу в буфер size байт, затем ищем '\n', пишем 0 после него, делаем lseek на нужную позицию. Вуаля!

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от kirk_johnson

Эти люди файлы mmap()'ом читают

А ты делаешь вид, что это неправильно! Самый простой способ. У меня большая часть велосипедов именно так файлы и читает. Сфигали проблемы возникнут? Ну если вдруг кто-то надумает обрезать файл, то получим SIGBUS и сдохнем. ИЧОСТОГО?

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от kirk_johnson

А потом кто-то сделает truncate

Сделать можно всё что угодно, от всего не застрахуешься. Юзер может и SIGKILL послать.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от Eddy_Em

Кстати, и такой способ я применял в случае, когда нужно только одну строчку из файла считать.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от true_admin

ГЫ:

    signal(SIGTERM, SIG_IGN);   // kill (-15)
    signal(SIGINT,  SIG_IGN);   // ctrl+C
    signal(SIGQUIT, SIG_IGN);   // ctrl+\   .
    signal(SIGTSTP, SIG_IGN);   // ctrl+Z
    signal(SIGTSTP, saygoodbye);// kill (-9)

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от kirk_johnson

А потом кто-то сделает truncate и ты получишь sigbus.

Эксперты подключились - ты же мне сможешь продемонстрировать sigbus на truncate()?

anonymous
()
Ответ на: комментарий от true_admin

Тьфу, я там скопипастил SIGTSTP и не заменил на SIGKILL.

// Да знаю я, что нельзя их перехватить.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от anonymous

Как вырезаете кусок?

Ммм, а разве FILE так умеет? Мне казалось системного вызова который позволяет выкинуть что-то из середины файла вообще нет. Хотя, теоретически, с гранулярностью в один блок это возможно.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Как и все. Открыл файл, дописал, закрыл. Если кусок вырезать, то тоже ничем не отличается от буферизованных операций: открыл файл источник, открыл с обнулением файл назначения, сделал в источнике lseek в нужную позицию и читай себе в буфер с записью в файл назначения...

Но в данном случае я бы тоже сделал тупым mmap'ом: mmap'им оба файла (файл назначения — на размер блока), а потом тупо while(--n) *dst++ = *src++;

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от kawaii_neko

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

Датычё.

char * stream = mmap_file(fd);
++stream;

Только тотальный и нулёвый 9-классник юзает fgets(), мне это не интересно и проблемы нулёвых адептов я не решаю.

anonymous
()
Ответ на: комментарий от Eddy_Em

не хватает нормальных ФС, которые позволяли бы такое вытворять...

Частично проблема решается дырявыми файлами. О, кстати, таки есть ФС которые таки это умеют: http://lwn.net/Articles/415889/

true_admin ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Пожалуйста. Вот вам пример из wiki питонщегов:

#!/usr/bin/python

import mmap
import time

# write a simple example file
with open("hello.txt", "wb") as f:
    f.write("Hello Python!\n")

with open("hello.txt", "r+b") as f:
    # memory-map the file, size 0 means whole file
    mm = mmap.mmap(f.fileno(), 0)
    time.sleep(5)
    # read content via standard file methods
    print mm.readline()  # prints "Hello Python!"
    # read content via slice notation
    print mm[:5]  # prints "Hello"
    # update content using slice notation;
    # note that new content must have same size
    mm[6:] = " world!\n"
    # ... and read again using standard file methods
    mm.seek(0)
    print mm.readline()  # prints "Hello  world!"
    # close the map
    mm.close()
(tty1)

$ ./test.py                  <-- after switch to tty2
$ zsh: bus error  ./test.py
(tty2)

$ truncate -s 0 hello.txt
kirk_johnson ★☆
()
Ответ на: комментарий от kawaii_neko

буферизация в первую очередь нужна для эффективной реализации форматированного ввода-вывода?

mmap «берёт» данные из page cache. И туда они попадают поблочно. Я пару лет назад видел сравнение mmap vs read, на больших файлах они работали примерно одинаково, но, правда, была куча нюансов. Есть ли readahead работает как надо то всё будет работать так же. А это зависит от версии ядра, ФС, планировщика ввода-вывода, драйверов, железа и погоды на марсе. С другой стороны, если стоят серьёзные задачи то без бенчмарков и тюнинга sysctl не обойтись.

реализовать char* fdgets(char *buf, int size, int fd)

С mmap точно так же, даже немного проще т.к. не надо следить что буфер достаточно полон. По крайней мере если сравнивать вот с этой реализацией: opensource.apple.com/source/Libc/Libc-167/stdio.subproj/fgets.c

Ну, типа

while(n-1<size && stream < file_end && stream !='\n')
    buf[n++]=stream++;
buf[n] = '\0'

true_admin ★★★★★
() автор топика
Ответ на: комментарий от kirk_johnson

Только truncate на файл это штатная ситуация.

Я абсолютно не понимаю почему стрельба в ногу это штатная ситуация. Тебе же не приходит в голову делать truncate на базы mysql или на postgres какой-нить. Ты не делаешь truncate на /lib/libc.so.6 . Ты не можешь просто так курочить файлы в системе и ожидать что программы это всё обработают.

Более того, пусть оно лучше упадёт чем заглючит или в файле будет мешанина из старых и новых данных.

Я тебе зато могу контр-пример привести. С буферизацией надо быть очень осторожным когда два процесса пишут в один файл. А с mmap у тебя консистентные данные по всем процессам.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от kirk_johnson

Можно в том же файле после mmap заменить time.sleep(5) на f.truncate() чтобы не прыгать в другую консоль.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

Можно. Я хотел показать общесистемность происходящего.

kirk_johnson ★☆
()
Ответ на: комментарий от true_admin

Более того, пЯ абсолютно не понимаю почему стрельба в ногу это штатная ситуация. Тебе же не приходит в голову делать truncate на базы mysql или на postgres какой-нить. Ты не делаешь truncate на /lib/libc.so.6 . Ты не можешь просто так курочить файлы в системе и ожидать что программы это всё обработают.усть оно лучше упадёт чем заглючит или в файле будет мешанина из старых и новых данных.

И откуда вы такие беретесь... Сюрприз: logrotate делает truncate на файлы, когда софт этого сам не умеет делать. И никто не падает.

kirk_johnson ★☆
()
Ответ на: комментарий от Eddy_Em

Открыл файл, дописал, закрыл
открыл файл источник, открыл с обнулением файл назначения

Имелся в виду такой сценарий: файл открыт для чтения/записи, время от времени нужно изменять, дописывать или вырезать кусок.

Если mmap-ить его целиком (допустим что файлы не очень большие и ОС не 32-битная), то перед каждым изменением размера придется делать munmap, «руками» (read/write) его изменять, а потом опять mmap? Ну, ок

anonymous
()
Ответ на: комментарий от kirk_johnson

Сюрприз: logrotate делает truncate на файлы, когда софт этого сам не умеет делать. И никто не падает.

Да что ты говоришь! Если он и делает подобную подлость, то только посредством сообщения демону об этом (шлет сигнал), иначе демон тупо отвалится нахрен!

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em
       copytruncate
              Truncate  the original log file to zero size in place after cre‐
              ating a copy, instead of moving the old log file and  optionally
              creating  a new one.  It can be used when some program cannot be
              told to close  its  logfile  and  thus  might  continue  writing
              (appending)  to  the previous log file forever.  Note that there
              is a very small time slice between copying the file and truncat‐
              ing it, so some logging data might be lost.  When this option is
              used, the create option will have no effect, as the old log file
              stays in place.
kirk_johnson ★☆
()
Ответ на: комментарий от Eddy_Em

Давай мы поговорим, когда ты перестанешь нюхать ацетон, ладно?

kirk_johnson ★☆
()
Ответ на: комментарий от anonymous

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

Ты не в курсе, что вырезать кусок из файла тупо невозможно? Для этого открывается новый файл, туда копируется голова, а потом хвост. Старый файл удаляется, новый переименовывается.

Если mmap-ить его целиком (допустим что файлы не очень большие и ОС не 32-битная), то перед каждым изменением размера придется делать munmap, «руками» (read/write) его изменять, а потом опять mmap? Ну, ок

На кой хрен? Я mmap'лю только входные файлы. А выходные тупо пишу тем же fprintf'ом при желании. Но чаще простым write.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от kirk_johnson

logrotate просто обязан послать демону сигнал, иначе демон сдохнет от truncate'а!

Ну ты и коняра... Как бы "царь" сказал, "нулëвый ваще".

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от kirk_johnson

И откуда вы такие беретесь

Давай без этого. Твоё высокомерие мешает тебе увидеть проблемы в твоей аргументации.

logrotate делает truncate на файлы

Пофиг, я логи никогда не стал бы писать через mmap (ты как себе это представляешь?). Там достаточно snprintf/write. Помимо этого, нормальный софт сам в доках напишет как ему ротировать логи.

Большинству софта вообще достаточно man 3 syslog, и не надо переизобретать велосипед.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от Eddy_Em

вырезать кусок из файла тупо невозможно?

Ну так нужно вырезать остро. Рассказываю секретный (очень) алгоритм: делаем seek на то место, которое нужно вырезать и начинаем копировать хвост файла ближе к голове

Эдуард, у вас там что, файлов больше 10 мегабайт не завозят?

Ты бы свои прогрессивные идеи попробовал на несколько-гигабайтных файлах что ли, и на 32-битной ОС, может слегка пришел бы в сознание

anonymous
()
Ответ на: комментарий от anonymous

Эдуард, у вас там что, файлов больше 10 мегабайт не завозят?

Ну тут как бэ не в размерах дело. При сдвигании хвоста к голове, не меняется файловый дескриптор, и по-хорошему фрагментация ФС снижается.

anonymous
()
Ответ на: комментарий от kirk_johnson

Ну, тогда я тебя поздравляю. Получается, что logrotate обрезает файл, а демон, т.к. об этом не знает, тупо продолжает писать по адресу, где у него текущий счетчик записей стоит. Гы.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от anonymous

делаем seek на то место, которое нужно вырезать и начинаем копировать хвост файла ближе к голове

Ну и копируй себе. Без буферизации это аналогично можно сделать.\

Эдуард, у вас там что, файлов больше 10 мегабайт не завозят?

У меня и по гигабайту файлы бывают. И ничего, работает все.

на 32-битной ОС

Такое встречается только на нетпуках и слабеньких ARM'ах. Но и там у меня отлично работает mmap, естественно, если файлы маленькие. Для больших я явно указываю использовать 64-битную адресацию и т.д., и т.п.

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

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от anonymous

Имелся в виду такой сценарий: файл открыт для чтения/записи, время от времени нужно изменять, дописывать или вырезать кусок.
вырезать кусок

Из файла куски не вырезаются не через жопу.

Всё просто - memmove() + msync(), если нужно + трункат.

то перед каждым изменением размера придется делать munmap

Нет, единственная проблема с ммапом - это дебильное поведение, которое не даёт расти файлу, когда ты выходишь за границы файла. Ну и та «бага» с трункатом с ноль.

Ты можешь спокойно заммапить килобайт на 100гигов, а после до каждого вызова юзать трункат. Можно даже сначала записать, а потом затрункатить, но тут может не фортануть и оно msync()«нет по середине и всё похериться.

«руками» (read/write) его изменять

Трункат, либо сик+врайт кастыль.

а потом опять mmap

Нет, есть mremap(), если тебе так уж хочется ремапить, что не нужно.

anonymous
()
Ответ на: комментарий от kawaii_neko

Зачем? Я наоборот стараюсь их отучить. А true_admin'а понесло и он сносит половину моих постов из-за боязни показаться некомпетентным.

kirk_johnson ★☆
()
Ответ на: комментарий от anonymous

Только тотальный и нулёвый 9-классник юзает fgets(), мне это не интересно и проблемы нулёвых адептов я не решаю.

А вот и первый адепт, который получил EACCESS (кстати, не забываем про ENODEV — mmap должен поддерживаться драйвером фс).

kawaii_neko ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.