LINUX.ORG.RU

Узнать PID процесса в драйвере ядра linux


0

1

Всем доброго времени суток. Возникла у меня такая дилемма - надо реализовать протокол модбас на встраиваемой системе (ARM7 nonMMU + uCLinux 2.6.21), в нем требуется отслеживать интервал тишины для определения окончания кадра, этот интервал на скорости 9600 составляет 4 мс, на моей платформе мне не удалось работать с интервалами меньше системного тика (10 мс), соответственно, штатными средствами я этот интервал выделить не могу. Почитал даташит на свой процессор (LPC 2468) и увидел, что там есть аппаратное прерывание на по истечении как раз этого самого интервала тишины (3,5 байта на текущей скорости). Нашел драйвер uart в линуксе, в нем обработчик прерываний от uart, все хорошо, прерывание отслеживается, но мне нужно дать сигнал userspace программе, что прошел интервал тишины, а значит можно считать, что кадр принят. И вот тут у меня небольшой стопор: как послать данные из драйвера? Сигналу требуется pid, его можно прочитать из файла, но пишут, что это читать-писать файлы из ядра - идеологически неправильно. проблема в том, что это обработчик прерывания, и тупить (блокироваться) там как минимум нежелательно. может в /proc? Есть ли возможность сделать свой модуль ядра с собственным обработчиком прерывания uart, отрабатывающим ПЕРЕД стандартным? еще варианты? Спасибо всем откликнувшимся.



Последнее исправление: titan83 (всего исправлений: 1)

В пространстве ядра есть указатель на текущий процесс - current, который имеет тип struct task_struct *, там есть поле pid, т.е. current->pid вернет pid текущего процесса. А вот где тебе его «ловить»... это уже другой вопрос.

Dennis7
()

Я сделал так:

int get_my_pid(char *proc_name)
{
        struct task_struct *task;

        for_each_process(task)
        {
                if((strcmp(task->comm, proc_name)==0))
                {
                        user_task = task;
                        return task->pid;
                }
        }
        return -1;
}
А когда нужно послать сигнал:
int kill_daemon()
{
        int ret = 0;
        struct siginfo info;
        memset(&info, 0, sizeof(struct siginfo));
        info.si_signo = SIGTERM;
        if(user_task > 0)
        {
                ret = send_sig_info(SIGTERM, &info, user_task);    //send the signal
                printk(KERN_ALERT "sent\n");
        }
        if (ret < 0) {
                printk("error sending signal\n");
                return ret;
        }
        return 0;
}

Deleted
()

Даже если current->pid у тебя будет не интересующего тебя процесса, то всегда можно «пройтись» по списку процессов, в ядре даже есть макросы для этого, list_for_each например

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

Как я понял, он хочет оповещать процесс из прерывания — там current нет, т.к. прерывание выполняется вне контекста какого-либо процесса.

В обработчике нужно запоминать значение и отдавать его интересующемуся процессу через системный вызов (убиват!), /proc или файл устройства /dev.

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

Как я понял, он хочет оповещать процесс из прерывания — там current нет, т.к. прерывание выполняется вне контекста какого-либо процесса.

Да. А я тред по диагонали прочитал.

Dennis7
()

на моей платформе мне не удалось работать с интервалами меньше системного тика (10 мс)

А задрать частоту не вариант?

еще варианты?

Конечно. Модуль должен реализовывать операцию poll над файловым дескриптором, а пользовательская программа должна вызывать этот poll.

tailgunner ★★★★★
()

Голосую за какой-нить псевдодевайс в /dev из которого можно читать из юзерспейса. Заодно юзерспейс-программа сможет понять что проспала «такт» если данных окажется больше чем приходит за один интервал.

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

то есть хочешь сказать, что сделать примерно как с GPIO?

Я не знаю, как сделано в GPIO :)

Там poll отдаёт POLLPRI при изменении уровня на пине.

Можно и так, но, мне кажется, это не тот случай. Я предпочитаю так, как сделано в RTC: почти нормальный файл, poll ждет готовности к чтению, а read читает нечто (счетчик прерываний или что там устройство может сообщить полезного).

НО! Правильнее всего было бы разобраться с таймерами платформы - ну не верю я, что там есть единственный источник прерываний с частотой всего 100Гц.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)

А userspace программа не может распознать без таймаута конец кадра ? Там же длина этого кадра в самом кадре забита и контрольная сумма. Пиши все подряд в буфер, а userspace пускай разбирается.

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

В модбас rtu переменная длина кадра и признаком его окончания служит интервал тишины длительностью 3,5 символа. Так что юзерспейс не разберется.

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

Задрать частоту чего? Если процессора - то нет, если системного таймера, то на него много чего завязано, я пробовал поднять до 1000 Гц, так не не смог загрузить - ошибки работы с файловой системой.

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

Вероятно, сделаю как раз через системный вызов, т.к. я изменяю стандартный драйвер uart, и хотелось бы ограничиться минимальными правками. Все равно на коммит мне этот вызов не выставлять.

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

Ты принятый кадр все равно пишешь в буфер который разбирает юзерспейс, что тебе мешает в это буфер записать и например условную последовательность байтов означающую интервал тишины прошел ? Если ты уж не хочешь конец посылки по длине и КС определять.

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

Задрать частоту чего?

Таймера.

я пробовал поднять до 1000 Гц, так не не смог загрузить - ошибки работы с файловой системой.

O_o

А таймер у вас единственный?

Вероятно, сделаю как раз через системный вызов

Welcome to Govnokod land.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

Можно и без таймера, выключить передатчик и сделать фиктивную передачу 4 байтов например, получить 4 прерывания, вот и искомый интервал на любой скорости. Вообще не понимаю зачем драйверу этот pid понадобился.

ilovewindows ★★★★★
()
Последнее исправление: ilovewindows (всего исправлений: 1)
Ответ на: комментарий от tailgunner

на счет говнокода с вами, к сожалению, полностью согласен(( но пока опыта в ядре мало, а Роберт Лав прочитан лишь один раз, приходится так колхозить( Смысл парится с таймером, если есть АППАРАТНОЕ прерывание по отсутствию новых данных в течение требуемого интервала?

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

И зачем это делать, если можно посмотреть состояние одного единственного бита и на основании его анализа понять, что произошло то, чего ты ждешь. Лучше делать проще, чем сложнее;) Но за внимание к теме в любом случае спасибо. Я уже сделал говнокод через syscall.

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

Смысл парится с таймером, если есть АППАРАТНОЕ прерывание по отсутствию новых данных в течение требуемого интервала?

Тогда у тебя есть возможность сделать нормально. Заодно и опыт приобретешь (и технический, и работы под давлением).

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