Страницы

Поиск по вопросам

Показаны сообщения с ярлыком прерывания. Показать все сообщения
Показаны сообщения с ярлыком прерывания. Показать все сообщения

воскресенье, 8 марта 2020 г.

Прерывание процесса и задержка на исполнение

#python #прерывания #subprocess


Подскажите, как осуществить прерывание системного процесса на Винде из питона? Допустим,
код выполняется до определенного момента, затем винда запускает внешний процесс, который
надо остановить и лишь потом продолжить выполнение кода. Так же интересует вопрос,
как добавить задержку перед выполнением следующего блока кода?
    


Ответы

Ответ 1



Чтобы прервать внешнюю команду через заданный промежуток времени, можно передать timeout параметр при её запуске: import subprocess subprocess.check_call(command, timeout=timeout) Если command не завершится через timeout секунд, то соответствующий процесс убивается и выбрасывается subprocess.TimeoutExpired исключение. Иногда этого не достаточно и необходимо руками убить всё дерево процессов, особенно если вы читаете вывод внешней команды. Вот пример кода, поддерживающий старые версии Питона (Python 2), который показывает как остановить "вечную" внешнюю команду через пару секунд, накапливая её вывод пока она выполняется. Если вы не хотите блокировать основной поток на время выполнения команды, то существует множество способов взаимодействия с командой асинхронно, чтобы найти примеры кода для разных случаев, следуйте по ссылкам. Если команда запущена вне Питона и вы хотите убить её через заданное время по имени: process = get_process_by_name(name) try: process.wait(timeout) except TimeoutExpired: process.kill() process.wait() .wait() завершается, если процесс вышел или время истекло—что раньше. Это очень близко к тому как subprocess.call() реализован. Существует множество других способов отложить запуск функции в Питоне, например, чтобы запустить функцию через timeout секунд, не блокируя основной поток всё это время: import threading threading.Timer(timeout, kill_process_by_name, [name]).start() ещё: time.sleep(timeout) или time.sleep(interval - timer() % interval), или Event.wait(timeout), или используя методы из соответствующих циклов обработки событий (event loop)—что выбрать, зависит от конкретной задачи. В общем случае, чтобы прервать выполнение функции в Питоне, см. Timeout on a function call. Примеры реализаций как можно найти процесс по имени и убить его: import psutil # $ pip install psutil def get_process_by_name(name): for proc in psutil.process_iter(): try: if proc.name() == name: return proc except psutil.NoSuchProcess: continue raise KeyError("Process {name!r} not found".format(name=name)) def kill_process_by_name(name): get_process_by_name(name).kill() def kill_process_tree_by_name_windows(name): subprocess.call(['taskkill', '/im', name, '/f', '/t'])

Ответ 2



import psutil import subprocess import time def proc_kill(proc_name): '''таск киллер''' for proc in psutil.process_iter(): if proc.name() == proc_name: psutil.Process(proc.pid).kill() print('внешний процесс %s который надо остановить' % proc_name) break if __name__ == '__main__': proc = 'calc.exe' # О процессе ,который надо завершить, известно его имя for r in range(5): print('Допустим, код выполняется до определенного момента') if r == 2: print('затем винда запускает внешний процесс %s' % proc) subprocess.Popen(proc) print('перед срабатыванием таск киллера необходима небольшая задержка') time.sleep(2) proc_kill(proc) # таск киллер print('и лишь потом продолжить выполнение кода') out: Допустим, код выполняется до определенного момента Допустим, код выполняется до определенного момента Допустим, код выполняется до определенного момента затем винда запускает внешний процесс calc.exe перед срабатыванием таск киллера необходима небольшая задержка внешний процесс calc.exe который надо остановить и лишь потом продолжить выполнение кода Допустим, код выполняется до определенного момента Допустим, код выполняется до определенного момента

понедельник, 16 декабря 2019 г.

Не работает обработчик прерывания

#c #ассемблер #gcc #прерывания


Почему этот код, меняющий обработчик прерывания клавиатуры, не работает на реальном
компьютере (выводит символ 'A' только 1 раз), хотя нормально работает в эмуляторах
bochs и qemu? Используется компилятор gcc, архитектура x86. 

asm(".code16gcc\n");

typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef struct __attribute__((__packed__)) FullAddr{
    ushort offset;
    ushort seg;
} FullAddr;

#define MAIN_CODE_START 0x9200

asm (
    "xorw %ax, %ax\n\t"
    "movw %ax, %ds\n\t"
    /*По этому адресу компоновщик помещает начало секции .data*/
    "movw (0x9202), %ax\n\t"
    "movw %ax, %ds\n\t"
    "movw %ax, %ss\n\t"
    "movw $0xFFFB, %sp\n\t" 
    "jmp main"
);

void print_char(char c){
    asm volatile("int  $0x10" : : "a"(0x0E00 | c), "b"(7));
}

void get_int_addr(ushort interrupt, FullAddr *addr)
{
    asm volatile(
        "pushw %%ds\n\t"
        "movw %w3, %%ds\n\t"
        "movw (%w2), %w0\n\t"
        "movw 2(%w2), %w1\n\t"
        "popw %%ds"
        : "=c"(addr->offset), "=a"(addr->seg):"b"(interrupt*4),"a"(0)
    );
}

void set_int_addr(ushort interrupt, uint func){
    asm volatile(
        "cli\n\t"
        "pushw %%ds\n\t"
        "movw %w2, %%ds\n\t"
        "movw %w0, (%w1)\n\t"
        "movw %%cs, 2(%w1)\n\t"
        "popw %%ds\n\t"
        "sti"
        : : "c"(func-MAIN_CODE_START), "b"(interrupt*4), "a"(0):
    );
}

void wait(uint usec)
{
    asm volatile("int $0x15": : "a"(0x8600), "c"(usec>>16), "d"(usec&0xFFFF));
}

FullAddr addr;

void handler_func(){
    print_char('A');
}

void handler();
asm(
    "handler:\n\t"
    "pushal\n\t"
    "call handler_func\n\t"
    "popal\n\t"
    "ljmp *addr\n\t"
    "iret\n\t"
);

void main(){
    get_int_addr(9, &addr);
    set_int_addr(9, (uint)handler);
    while(1){
        wait(1000);
    }
}


На всякий случай выкладываю полный код проекта , включающий образ дискеты (может,
кто-нибудь запустит). Для компиляции нужно запустить файлы build.sh и build_main.sh.
    


Ответы

Ответ 1



На английской версии SO подсказали, что проблема в значении сегмента %ds, которое может измениться внутри обработчика прерывания 0x15 ( функция wait) в BIOS. И в этот момент может сработать прерывание 0x9, которое я перехватываю. А в обработчике последнего, как раз используется сегмент %ds (ljmp *addr). То есть, переход будет не туда, куда нужно. Решение: каждый раз в функции handler менять %ds на своё значение, а в конце функции возвращать старое. Код: void handler(); asm( "handler:\n\t" "pushw %ds\n\t" "pushal\n\t" "xorw %ax, %ax\n\t" "movw %ax, %ds\n\t" "movw (0x9202), %ax\n\t" "movw %ax, %ds\n\t" "call handler_func\n\t" "pushfw\n\t" "lcallw *addr\n\t" "popal\n\t" "popw %ds\n\t" "iretw\n\t" );

понедельник, 27 мая 2019 г.

Прерывание процесса и задержка на исполнение

Подскажите, как осуществить прерывание системного процесса на Винде из питона? Допустим, код выполняется до определенного момента, затем винда запускает внешний процесс, который надо остановить и лишь потом продолжить выполнение кода. Так же интересует вопрос, как добавить задержку перед выполнением следующего блока кода?


Ответ

Чтобы прервать внешнюю команду через заданный промежуток времени, можно передать timeout параметр при её запуске:
import subprocess
subprocess.check_call(command, timeout=timeout)
Если command не завершится через timeout секунд, то соответствующий процесс убивается и выбрасывается subprocess.TimeoutExpired исключение. Иногда этого не достаточно и необходимо руками убить всё дерево процессов, особенно если вы читаете вывод внешней команды. Вот пример кода, поддерживающий старые версии Питона (Python 2), который показывает как остановить "вечную" внешнюю команду через пару секунд, накапливая её вывод пока она выполняется. Если вы не хотите блокировать основной поток на время выполнения команды, то существует множество способов взаимодействия с командой асинхронно, чтобы найти примеры кода для разных случаев, следуйте по ссылкам
Если команда запущена вне Питона и вы хотите убить её через заданное время по имени:
process = get_process_by_name(name) try: process.wait(timeout) except TimeoutExpired: process.kill() process.wait()
.wait() завершается, если процесс вышел или время истекло—что раньше. Это очень близко к тому как subprocess.call() реализован
Существует множество других способов отложить запуск функции в Питоне, например, чтобы запустить функцию через timeout секунд, не блокируя основной поток всё это время:
import threading
threading.Timer(timeout, kill_process_by_name, [name]).start()
ещё: time.sleep(timeout) или time.sleep(interval - timer() % interval), или Event.wait(timeout), или используя методы из соответствующих циклов обработки событий (event loop)—что выбрать, зависит от конкретной задачи. В общем случае, чтобы прервать выполнение функции в Питоне, см. Timeout on a function call
Примеры реализаций как можно найти процесс по имени и убить его:
import psutil # $ pip install psutil
def get_process_by_name(name): for proc in psutil.process_iter(): try: if proc.name() == name: return proc except psutil.NoSuchProcess: continue raise KeyError("Process {name!r} not found".format(name=name))
def kill_process_by_name(name): get_process_by_name(name).kill()
def kill_process_tree_by_name_windows(name): subprocess.call(['taskkill', '/im', name, '/f', '/t'])

суббота, 27 октября 2018 г.

Не работает обработчик прерывания

Почему этот код, меняющий обработчик прерывания клавиатуры, не работает на реальном компьютере (выводит символ 'A' только 1 раз), хотя нормально работает в эмуляторах bochs и qemu? Используется компилятор gcc, архитектура x86.
asm(".code16gcc
");
typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; typedef struct __attribute__((__packed__)) FullAddr{ ushort offset; ushort seg; } FullAddr;
#define MAIN_CODE_START 0x9200
asm ( "xorw %ax, %ax
\t" "movw %ax, %ds
\t" /*По этому адресу компоновщик помещает начало секции .data*/ "movw (0x9202), %ax
\t" "movw %ax, %ds
\t" "movw %ax, %ss
\t" "movw $0xFFFB, %sp
\t" "jmp main" );
void print_char(char c){ asm volatile("int $0x10" : : "a"(0x0E00 | c), "b"(7)); }
void get_int_addr(ushort interrupt, FullAddr *addr) { asm volatile( "pushw %%ds
\t" "movw %w3, %%ds
\t" "movw (%w2), %w0
\t" "movw 2(%w2), %w1
\t" "popw %%ds" : "=c"(addr->offset), "=a"(addr->seg):"b"(interrupt*4),"a"(0) ); }
void set_int_addr(ushort interrupt, uint func){ asm volatile( "cli
\t" "pushw %%ds
\t" "movw %w2, %%ds
\t" "movw %w0, (%w1)
\t" "movw %%cs, 2(%w1)
\t" "popw %%ds
\t" "sti" : : "c"(func-MAIN_CODE_START), "b"(interrupt*4), "a"(0): ); }
void wait(uint usec) { asm volatile("int $0x15": : "a"(0x8600), "c"(usec>>16), "d"(usec&0xFFFF)); }
FullAddr addr;
void handler_func(){ print_char('A'); }
void handler(); asm( "handler:
\t" "pushal
\t" "call handler_func
\t" "popal
\t" "ljmp *addr
\t" "iret
\t" );
void main(){ get_int_addr(9, &addr); set_int_addr(9, (uint)handler); while(1){ wait(1000); } }
На всякий случай выкладываю полный код проекта , включающий образ дискеты (может, кто-нибудь запустит). Для компиляции нужно запустить файлы build.sh и build_main.sh.


Ответ

На английской версии SO подсказали, что проблема в значении сегмента %ds, которое может измениться внутри обработчика прерывания 0x15 ( функция wait) в BIOS. И в этот момент может сработать прерывание 0x9, которое я перехватываю. А в обработчике последнего, как раз используется сегмент %ds (ljmp *addr). То есть, переход будет не туда, куда нужно. Решение: каждый раз в функции handler менять %ds на своё значение, а в конце функции возвращать старое. Код:
void handler(); asm( "handler:
\t" "pushw %ds
\t" "pushal
\t" "xorw %ax, %ax
\t" "movw %ax, %ds
\t" "movw (0x9202), %ax
\t" "movw %ax, %ds
\t" "call handler_func
\t" "pushfw
\t" "lcallw *addr
\t" "popal
\t" "popw %ds
\t" "iretw
\t" );