LINUX.ORG.RU

обработчик сигнала


0

0

Всем привет!

Такая проблем: пишу лабу на Си под Линукс. С помощью sigaction'а установил обработчик сигнала для проги. А как сделать, чтобы этот-же обработчик был и для вызываемой сторонней программы через system ()??

На примере:

main () { /*введена структура обработчика прерываний sa*/ sigaction (SIGINT, &sa, NULL); /*какие-то действия*/ system ("cp file1.txt file2.txt"); }

Как сделать, чтобы обработчик из структуры sa обрабатывал прерывания, вызванные во время выполнения cp??

Ответ на: комментарий от watashiwa_daredeska

Прямо так категорично? То бишь, во время выполнения программы cp - она прервется. А можно хотя-бы узнать, что прерывание ваще пришло и запустить cp заново?

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

да, прямо так категорично. Прервется запускаемая вами программа или не прервется, а так же её код возврата - глубоко интимное дело автора запускаемой программы.

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

так же внимательно читать про system() ну и вообще про execve()/fork()/signal handling

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

> Прямо так категорично?

Да. То, что ты хочешь --- офигенной величины дыра в security.

> То бишь, во время выполнения программы cp - она прервется.

Смотря какой сигнал получит.

> А можно хотя-бы узнать, что прерывание ваще пришло и запустить cp заново?

Как уже советовали: man fork, exec{l,v}{,p,e}, waitpid. Узнать, что дочерний процесс завершился можно и даже нужно. При определенных условиях (которые соблюдают все нормальные программы) можно узнать успешность выполнения и/или сигнал, который вызвал завершение.

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

> Смотря какой сигнал получит.

Получает только сигнал SIGINT по Ctrl+C

Далее.. Получит или не получит дочерний процесс сигнал - я узнаю по статусу, возвращаемому через wait(&status) - с этим разобрался.

Еще раз напишу прогу:

if (fork() == 0) {

system ("cp file1 file2");

} else {

wait (&status);

if (WIFSIGNALED(status) == 1) printf ("Copying terminated by a signal");

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

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

1. Если system(), то fork() не нужен. system сам делает fork/exec/wait и возвращает статус.

> Далее идет сравнение размеров файлов file1 и file2 - а в этом проблема

man 2 stat

> cp завершается раньше, чем файлы по-настоящему скопируются

=8-[ ] Так не бывает. Точнее бывает, но это жуткий глюк, который бы уже выловили за 20 лет, поэтому не бывает.

> так как используется буфер.

Ты имеешь в виду буферизацию и кэширование в ОСи? Забудь, оно для тебя прозрачно, т.е. незаметно.

> Может этот буфер можно как-то отключить?

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

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

> man 2 stat

У меня fstat - это я уже знаю

> cp завершается раньше, чем файлы по-настоящему скопируются

Нее, по-моему тут как-раз sync или fsync помогает! Заметно-незаметно, но когда я копирую большие файлы (пусть просто в консоли, большие - чтобы заметно было отставание), то у меня приглашение на ввод следующей команды будет раньше, чем диск кончит писать файл. Так что тут синхронизация как-раз и нужна вроде.

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

>> cp завершается раньше, чем файлы по-настоящему скопируются

>=8-[ ] Так не бывает. Точнее бывает, но это жуткий глюк, который бы уже выловили за 20 лет, поэтому не бывает.

Этот "глюк" я наблюдаю каждый раз, когда работаю с USB-флешкой. Например, при копировании файла ок. 50 метров реально копируется где-то 1/3, остальное дописывается при извлечении. Что будет, если флешку вынуть сразу после cp?

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

>Этот "глюк" я наблюдаю каждый раз, когда работаю с USB-флешкой. Например, при копировании файла ок. 50 метров реально копируется где-то 1/3, остальное дописывается при извлечении. Что будет, если флешку вынуть сразу после cp?

ДА-да, именно так. Для этого нужно сделать команду sync - она все синхронизирует. При umount /usb тоже автоматом запускается sync.

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

> файлы по-настоящему скопируются

Мы, видимо, расходимся в понимании того, что значит "по-настоящему" :)

> у меня приглашение на ввод следующей команды будет раньше, чем диск кончит писать файл.

В первый раз в первый класс...

То, что данные еще продолжают скидываться на диск, еще не означает, что файла нет, или он не полон. Он есть! Система о нем знает, его можно читать (и даже получить ровно то же самое, что записал, как ни странно ;) ). Write-behind cache --- внутреннее дело системы.

> тут как-раз sync или fsync помогает!

man2 sync: BUGS According to the standard specification (e.g., POSIX.1-2001), sync() schedules the writes, but may return before the actual writing is done. However, since version 1.3.20 Linux does actually wait. (This still does not guaran‐ tee data integrity: modern disks have large caches.)

man fsync: NOTES If the underlying hard disk has write caching enabled, then the data may not really be on permanent storage when fsync() / fdatasync() return.

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

> При umount /usb тоже автоматом запускается sync.

Не совсем. При umount'е синхрится только то устройство, которое отмонтируется, а по sync() у тебя система будет скидывать кэши всех устройств.

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

>Не совсем. При umount'е синхрится только то устройство, которое отмонтируется, а по sync() у тебя система будет скидывать кэши всех устройств.

Это - да, согласен.

Но факт остается фактом - после system ("cp file1 file2") я сравниваю размеры и они разные! А если сравниваю размеры через 5 секунд (sleep(5)), то уже одиннаковые - докопировалось...

И то, что я к копируемому файлу сразу могу обращаться (и в любую точку этого файла) - это я знаю

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

> факт остается фактом - после system ("cp file1 file2") я сравниваю размеры и они разные!

Неправильно как-то сравниваешь. У меня Ok.

> то, что я к копируемому файлу сразу могу обращаться (и в любую точку этого файла) - это я знаю

Теперь объясни мне логику --- размер еще не правильный, а данные уже правильные?

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

Во-первых, у меня не установлен DMA, так что отчасти я могу валить на него.

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

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

> Во-первых, у меня не установлен DMA, так что отчасти я могу валить на него.

DMA тут ну совершенно не пришей кобыле хвост.

> если сразу после этого копирования я обращаюсь к любой части файла, а она (часть) застряла в буфере (то бишь да диске мЕньший размер, чем должен быть),

Объясняю. На том уровне абстракции, на котором ты работаешь, абсолютно пофиг, где данные --- на диске, в буфере, в кэше файл-сервера, в кабеле между машиной и файл-сервером или в радиоволне между Землей и Марсом :) Если ты дописал в конец файла N байт, то размер файла _тут_же_ увеличился на N и эти N байт из него можно прочитать. Из этих правил есть исключения, но к твоему случаю они неприменимы.

> то она сразу докопирывается и я имею к ней доступ (а может, система сразу берет ее из буфера).

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

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

>Далее идет сравнение размеров файлов file1 и file2 - а в этом проблема, так как cp завершается раньше, чем файлы по-настоящему скопируются, так как используется буфер. Может этот буфер можно как-то отключить?

Товарищ, объясняю на пальцах. Кэширование - это сугубо внутреннее дело ОС. Когда cp выполнился, то файл скопировался полностью. Если какие-то блоки с данными или метаданными и не попали на физическое устройство, то с точки зрения процесса ты этого увидеть не можешь, поскольку ОС всегда представляет целостный образ файловой системы (любой вменяемый механизм кэширования так работает). Размер файла для VFS всегда изменяется синхронно и никто его после завершения cp менять не будет. После завершения cp размеры файлов ОБЯЗАТЕЛЬНО РАВНЫ и полученные при чтении данные тоже ОБЯЗАТЕЛЬНО ОДИНАКОВЫ (даже если скопированный файл читается через O_DIRECT).

Если у тебя чего-то там не синхронно, то это значит, что ты просто неправильно дожидаешься завершения cp, вот и все.

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

вообщем, вставил я fsync и все работает:))

Всем спасибо за внимание!

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

>ну а (f)sync тогда для чего??

sync/fsync - это системная вещь. И заботить она тебя должна в последнюю очередь.

>вообщем, вставил я fsync и все работает:))

поскольку fsync не имеет абсолютно никакого отношения к написанному, то, очевидно, не заработала, тем более, что непонятно, как ты во внешнюю программу (cp) вставил fsync.

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

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

Так... Господин Анонимус!

Я не понимаю ваших слов про последнюю очередь. Если без fsync у меня размер после копирования не соответствует нужному (то бишь часть файла (на момент завершения копирования (выход из команды cp)) застревает в буфере), а с fsync - все правильно, значит он тут даже очень при чем.

1-ый вариант)

system ("cp f1 f2");

fstat(...);

---размер неправильный

2-ой вариант)

system ("cp f1 f2");

fsync (f2);

fstat(...);

---размер f2 = размеру f1 --- все верно! И кто говорит про ненужность fsync?

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

fd2 = open (name2, O_WRONLY | O_CREAT, 0666 );

Open выполняется в самом начале проги, до fstat и fsync. Надо его закрыть что-ли перед system'ом?

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

>Я не понимаю ваших слов про последнюю очередь. Если без fsync у меня размер после копирования не соответствует нужному (то бишь часть файла (на момент завершения копирования (выход из команды cp)) застревает в буфере), а с fsync - все правильно, значит он тут даже очень при чем.

Вы вообще представляете, как работает fsync? Ему же нужен FILE* :) Или вы специально открываете файл из родительского процесса, чтобы сделать fsync? :-O И, по-вашему, это сколь-либо внятное действие?

То, что с fsync у вас видимость работы, объясняется очень просто - у вас создается дополнительная задержка при синхронизации с диском и race при проверке проявляется реже.

Еще раз подчеркиваю: после завершения cp НЕ НУЖНО никаких fsync, независимо от того, записал ли VFS данные на диск или нет, он будет через fstat возвращать корректные данные.

Приведите целиком код вашей программы и мы найдет ошибку.

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

[ tmp]# cat ppp.c
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char* argv[]) {
    int f1, f2;
    struct stat buf1, buf2;
    char cmd[100];

    sprintf(cmd, "/bin/cp %s %s", argv[1], argv[2]);
    system(cmd);

    f1 = open(argv[1], O_RDONLY);
    assert(f1>=0);
    f2 = open(argv[2], O_RDONLY);
    assert(f2>=0);

    assert(fstat(f1, &buf1)>=0);
    assert(fstat(f2, &buf2)>=0);

    printf("f1.size=%lu f2.size=%lu\n", (unsigned long)buf1.st_size, (unsigned long)buf2.st_size);

    return 0;
}
[ tmp]# gcc ppp.c
ppp.c: In function &#8216;main&#8217;:
ppp.c:10: warning: incompatible implicit declaration of built-in function &#8216;sprintf&#8217;
ppp.c:21: warning: incompatible implicit declaration of built-in function &#8216;printf&#8217;
[ tmp]# dd if=/dev/zero of=tmpfile1 bs=1048576 count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 3.00636 seconds, 34.9 MB/s
[ tmp]# time ./a.out tmpfile1 tmpfile2
f1.size=104857600 f2.size=104857600

real    0m8.517s
user    0m0.016s
sys     0m1.172s

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

> Скорее всего, у тебя кэшируется инфа при открытии и не успевает обновиться после system. Попробуй [пере]открыть после system.

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

anonymous
()

Спор ни о чем :) Код приведите пожалуйста. Желательно полный.

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