Сожалеем, но текст оригинала доступен только зарегистрированным пользователям. |
17.7. Обработка прерываний
hardorsoft
26.10.10 в 02:54
|
|
Управление большинством устройств осуществляется через прерывания. Аппаратное прерывание процессору сигнализирует об одном из двух возможных событий: прибытие нового пакета или завершение передачи пакета. Сетевой интерфейс может так же генерировать прерывания при ошибках, изменении статуса соединения и т.д.
hardorsoft
26.10.10 в 02:54
|
|
Обычно обработчик прерывания проверяет регистр состояния устройства, для определения причины прерывания. Аналогично работает интерфейс snull, но слово состояния реализовано программно и находится в dev->priv. Обработчик прерывания сетевого интерфейса выглядит примерно так:
hardorsoft
26.10.10 в 02:54
|
|
static void snull_regular_interrupt(int irq, void *dev_id, struct pt_regs *regs) { int statusword; struct snull_priv *priv; struct snull_packet *pkt = NULL; /* * как обычно проверяем указатель "device" * чтобы убедится, что это действительно прерывание * затем присваиваем "struct device *dev" */ struct net_device *dev = (struct net_device *)dev_id; /* ... и проверяем аппаратуру*/ /* paranoid */ if (!dev) return; /* блокируем устройство */ priv = netdev_priv(dev); spin_lock(&priv->lock); /* Находим слово состояния: настоящее устройство использует */ /* инструкции ввода-вывода */ statusword = priv->status; priv->status = 0; if (statusword & SNULL_RX_INTR) { /* send it to snull_rx for handling */ /* выполняем snull_rx для обработки */ pkt = priv->rx_queue; if (pkt) { priv->rx_queue = pkt->next; snull_rx(dev, pkt); } } if (statusword & SNULL_TX_INTR) { /* передача завершена, освобождаем skb*/ priv->stats.tx_packets++; priv->stats.tx_bytes += priv->tx_packetlen; dev_kfree_skb(priv->skb); } /* разблокируем устройство */ spin_unlock(&priv->lock); if (pkt) snull_release_buffer(pkt); /* выполняется вне блокировки*/ return; }
hardorsoft
26.10.10 в 02:55
|
|
В первую очередь, обработчик убеждается в корректном значении указателя на структуру net_device. Этот указатель приходит как аргумент.
hardorsoft
26.10.10 в 02:55
|
|
Рассмотрим происходящее при завершении передачи пакета. В этом случае обновляется статистика, и вызывается dev_kfree_skb для возврата, более не нужного, буфера сокета системе. Есть 3 варианта этой функции.
hardorsoft
26.10.10 в 02:55
|
|
dev_kfree_skb(struct sk_buff *skb);
hardorsoft
26.10.10 в 02:55
|
|
Эта версия вызывается, если вы точно знаете, что не работаете в контексте прерывания. Так как snull не имеет аппаратных прерываний, мы используем эту версию.
hardorsoft
26.10.10 в 02:56
|
|
dev_kfree_skb_irq(struct sk_buff *skb);
hardorsoft
26.10.10 в 02:56
|
|
Если вы знаете что работаете в используйте эту версию функции.
hardorsoft
26.10.10 в 02:56
|
|
dev_kfree_skb_any(struct sk_buff *skb);
hardorsoft
26.10.10 в 02:56
|
|
Эта версия может использоваться как в контексте прерывания, так и вне его.
hardorsoft
26.10.10 в 02:56
|
|
В конце, если ваш драйвер приостанавливает очередь передачи, как правило производят и повторный старт netif_wake_queue.
hardorsoft
26.10.10 в 02:57
|
|
Прием пакетов, в противоположность передачи, не нуждается в специальной обработке прерывания. Все что требуется это вызов snull_rx (который мы уже рассмотрели).
hardorsoft
26.10.10 в 02:57
|
|