实时捕捉以太网原始数据包(PacketRawEthernetMonitor)----Kithara RTS工程源代码解析

本文以windows实时拓展Kithara RTS安装目录下的smp文件夹内的PacketRawEthernetMonitor工程源码为例,
该源码实现了一个简单的网络监视程序,可以实时监测网卡接收的原始数据。
该工程主要使用了Kernel,Packet模块,有三个函数组成:主函数runSample,回调函数_callBack,线程_recvThread,_callBack和_recvThread之间存在着同步关系,线程_recvThread运行时会堵塞等待事件,回调函数设置该事件后线程才能继续运行。
程序运行过程如下:
1、进入主函数,打开kithara RTS,建立共享内存区域,枚举以太网卡并选择一个需要的网卡,建立一个管道,用于回调函数与接收线程之间的数据交互
2、创建一事件(event),用于回调函数_callBack和线程_recvThread之间的同步。
3、创建线程_recvThread,该线程开始即处于阻塞状态,等待事件被设置。事件被设置后,本线程将继续运行,从管道中取出数据并在屏幕上显示。
4、创建回调函数_callBack,在网卡接收到数据时将触发该回调函数运行,该函数的作用是将接收的数据包存入管道中,然后设置事件以触发_recvThread继续运行。
5、创建一个标志位,如果置为false,recvThread线程进入while循环,等待事件触发其读取管道中的数据并显示;如果置为ture,线程函数不再读取数据,
6、使用函数KS_installPacketHandler将网卡数据接收事件和回调函数_callBack关联,然后设置事件,此时程序进入正式的工作状态。
7、最后退出程序,首先停止数据读取,取消回调函数关联,然后进行资源回收处理工作。

// Used Modules:     Kernel Module, Packet Module//使用到的模块
//
// Descript.:        Sample application showing how to implement a raw
//                   ethernet monitor application  //形成一个以太网监视应用程序
// Purpose:
//
// This example shows how to program a raw ethernet monitoring application.
//该例子展示了如何编制一个基本的以太网监视程序
// First, the program opens the driver and the Ethernet adapter.//首先,打开驱动及网卡适配器
// We install the receiver callback.安装接收器回调函数
// A receive thread is displaying the mac header, which is submitted by a pipe. 接收线程通过管道显示mac头
// Finally we release all used resources and close the driver.最后清理资源
//
// Attention! It is nessary that there is no switch between our adapter and the adapter we want to trace!不能对适配器进行切换
// Otherwise, only broadcast messages will be monitored!  否则只能监视反馈回来的信息
//
// ATTENTION! Network cards can only be used here, when the driver of the card has been switched to Kithara!
// It is not possible to use the original driver for real-time! Please refer to the manual, chapter 16
// "Packet Module" for further instructions on switching the driver to Kithara!

#include "..\_KitharaSmp\_KitharaSmp.h"

const char* pCustomerNumber = "DEMO";

//--------------------------------------------------------------------------------------------------------------
// This is a user defined argument structure to the callback routine.用户定义回调函数结构体
// You are free to define your own arguments in any record/class.
//--------------------------------------------------------------------------------------------------------------

//------ CallBackData ------
struct CallBackData {   //回调数据的结构体,
  Handle hAdapter_;     //适配器句柄
  Handle hCallBack_;    //回调函数句柄
  Handle hEvent_;       //事件句柄
  Handle hPipe_;        //管道句柄
  bool finished_;       //标志位
};

//当接收到数据包时,将数据包地址存在管道中
//--------------------------------------------------------------------------------------------------------------
// These are user defined callback routines. They are called every time a packet is received.一下定义回调函数,当有数据包接收到的时候调用
// We put the data in a pipe and set the receive event. 将数据放入管道中,设置接收数据的事件
//--------------------------------------------------------------------------------------------------------------

//------ _callBack ------回调函数的定义
static Error __stdcall _callBack(void* pArgs, void* pContext) {
  CallBackData* pData = (CallBackData*)pArgs;
  PacketUserContext* pUserContext = (PacketUserContext*)pContext;

  Error ksError;

  ksError = KS_putPipe(                                 // 将数据包地址放入管道中
              pData->hPipe_,                            // Pipe handle,管道对应的句柄
              &pUserContext->pPacketApp,                // Address of pointer to packet,待存入管道中的数据内存地址,这里是接收的数据包地址
              1,                                        // Item count,数量
              NULL,                                     // Number of bytes transmitted ,Number of bytes transmitted so far.
              0);                                       // Flags, here none
  if (ksError != KS_OK)
    return ksError;

  ksError = KS_setEvent(                                // 设置事件,触发线程继续运行
              pData->hEvent_);                          // Event handle事件句柄
  if (ksError != KS_OK)
    return ksError;

  return KS_OK;
}

//--------------------------------------------------------------------------------------------------------------
// This is the user defined thread function. It contains a loop in which the thread waits for the event
// signalization whenever a packet is received.线程,等待事件信号,然后将管道中的数据取出并显示数据包头,最后释放数据包的内存对象
// After displaying the packet header, the packet must be released with KS_releasePacket.
//--------------------------------------------------------------------------------------------------------------

Error __stdcall _recvThread(void* pArgs) {//也是一个回调函数,接收数据的线程

  Error ksError = KS_OK;
  CallBackData* pData = (CallBackData*)pArgs;

  while (!pData->finished_) {             //

    //----------------------------------------------------------------------------------------------------------
    // Wait for the event to be set.
    //----------------------------------------------------------------------------------------------------------

    ksError = KS_waitForEvent(                          // 等待接收数据
                pData->hEvent_,                         // Event handle在回调函数中定义的事件
                0,                                      // Flags
                0);                                     // Time-out, in 100-ns-units
    if (ksError != KS_OK)
      return ksError;

    KSMACHeader* pHeader;
    while (KS_getPipe(pData->hPipe_, &pHeader, 1, NULL, 0) == KS_OK) {
      outputTxt(" ", true);//读出管道中的数据,并显示出来
      for (int i = 0; i < 3; ++i)
        outputHex(KS_ntohs(*(ushort*)&pHeader->source[i * 2]), "", "", false);

      outputTxt(" -> ", false);

      for (int i = 0; i < 3; ++i)
        outputHex(KS_ntohs(*(ushort*)&pHeader->destination[i * 2]),
                  "", "", false);
      outputHex(KS_ntohs(pHeader->typeOrLength), " typeOrLength: ", "", false);

      //--------------------------------------------------------------------------------------------------------
      // Finally we release the packet.最后清空数据包
      //--------------------------------------------------------------------------------------------------------

      ksError = KS_releasePacket(//释放数据包
                  pData->hAdapter_,                     // Adapter handle,网卡句柄
                  pHeader,                              // Pointer to packet,指向数据包的指针
                  KSF_RAW_ETHERNET_PACKET);             // Flags,标志
      if (ksError != KS_OK)
        return ksError;
    }
  }

  outputTxt("Thread has been finished.");
  return ksError;
}

//--------------------------------------------------------------------------------------------------------------
// This is the main program 主函数
//--------------------------------------------------------------------------------------------------------------

void runSample() {
  outputTxt("***** Kithara example program ‘PacketRawEthernetMonitor‘ *****");

  Error ksError;
  ///////////////////////////////////////////////////////////////////////  //////1.程序初始化  ///////////////////////////////////////////////////////////////////////
  //------------------------------------------------------------------------------------------------------------
  // Opening the driver is always the first step! After that, we can use other functions. If the opening fails,
  // no other function can be called.
  //
  // This function takes your customer number with Kithara (or "DEMO" or "BETA" if applicable) as a parameter.
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_openDriver(//第一步,打开驱动
              pCustomerNumber);                         // Customer number 已定义const char* pCustomerNumber = "DEMO";
  if (ksError) {
    outputErr(ksError, "KS_openDriver", "Maybe incorrect customer number?");
    return;
  }

  //------------------------------------------------------------------------------------------------------------
  // Allocation of Sharedmem分配共享内存
  //------------------------------------------------------------------------------------------------------------

  CallBackData* pAppPtr; //结构体指针
  CallBackData* pSysPtr;
  ksError = KS_createSharedMem(//创建共享内存
              (void**)&pAppPtr,                         // App Pointer
              (void**)&pSysPtr,                         // Sys Pointer
              "MyPacketRawEthernetMonitorMemory",       // Name
              sizeof(CallBackData),                     // Size大小为定义的结构体大小
              0);                                       // Flags
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_createSharedMem",
      "Failed to allocate shared memory");
    KS_closeDriver();
    return;
  }

  //------------------------------------------------------------------------------------------------------------
  // First, the names of all network adapters are queried and displayed首先,查询并显示所有网络适配器
  //------------------------------------------------------------------------------------------------------------

  char pDeviceName[256];//定义一个大小为256的char型数组

  outputTxt(" ");
  outputTxt("Following network adapters found:");

  for (int i = 0; ; ++i) {

    //----------------------------------------------------------------------------------------------------------
    // The following function can be used to query the names of all network adapters assigned to the Kithara
    // Driver. The number ‘i‘ runs beginning from zero.
    //枚举可用的网卡适配器,选择一个使用
    // ATTENTION! Network cards can only be used here, when the driver of the card has been switched to Kithara!
    // It is not possible to use the original driver for real-time! Please refer to the manual, chapter 16
    // "Packet Module" for  further instructions on switching the driver to Kithara!
    //----------------------------------------------------------------------------------------------------------

    ksError = KS_enumDevices(//枚举设备的函数
                "NET",                                  // Searches for network devices,专门寻找有关网络的设备
                i,                                      // Count, starting with zero计数
                pDeviceName,                            // Buffer for device name 设备名称
                0);                                     // Flags
    if (ksError != KS_OK) {
      if (KSERROR_CODE(ksError) != KSERROR_DEVICE_NOT_FOUND)
        outputErr(ksError, "KS_enumDevices",
          "Unable to query network device name!");

      if (KSERROR_CODE(ksError) == KSERROR_DEVICE_NOT_FOUND && !i) {
        outputTxt("No devices found");
        outputTxt(" ");
        outputTxt("Did you switch the network card driver to Kithara?");
        outputTxt("Please refer to the manual, chapter 16 \"Packet Module\"");
        outputTxt("for further instructions!");
        KS_closeDriver();
        return;
      }

      break;
    }

    outputDec(i, "", ": ", false);
    outputTxt(pDeviceName);
  }
  outputTxt(" ");

  //------------------------------------------------------------------------------------------------------------
  // Please enter the index of the adapter, which should be opened上一个函数时枚举,现在选择,index不同,选择好,打开网络适配器
  //------------------------------------------------------------------------------------------------------------

  int deviceIndex = inputDec("Device number: ", "");

  ksError = KS_enumDevices(
              "NET",                                    // Searches for network devices
              deviceIndex,                              // Index of device
              pDeviceName,                              // Buffer for device name
              0);                                       // Flags
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_enumDevices",
      "Unable to query network device name!");
    KS_closeDriver();
    return;
  }

  outputTxt("Selected device: ", false);
  outputTxt(pDeviceName);

  //------------------------------------------------------------------------------------------------------------
  // Then we open the network adapter.
  //
  // Please enter a part of the hardware ID of your network controller.
  // e.g.
  // Intel: "VEN_8086"
  // Realtek: "PCI\\VEN_10EC&DEV_8139" or "DEV_8139"
  //------------------------------------------------------------------------------------------------------------
  //选择好之后,打开选择好的网卡适配器
  ksError = KS_openAdapter(
              &pAppPtr->hAdapter_,                      // Adapter handle
              pDeviceName,                              // Device name of the adapter
              100,                                      // Receive Pool Length
              0,                                        // Send Pool Length
              KSF_RAW_ETHERNET_PACKET |
              KSF_ACCEPT_ALL);                          // Flags
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_openAdapter", "Failed to open adapter");
    KS_closeDriver();
    return;
  }

  //------------------------------------------------------------------------------------------------------------
  // Here we set a mac multicast address, cause we want to display all packets going to this address.设置一个mac地址,来显示经过此地址的数据包
  // It is necessary that there is no network switch between our adapter and the adapter we want to trace
  //注意:适配器跟要追溯的适配器不能切换
  //------------------------------------------------------------------------------------------------------------

  byte multi[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  ksError = KS_execAdapterCommand(//对网络适配器进行操作
              pAppPtr->hAdapter_,                       // Adapter handle
              KS_PACKET_SET_MAC_MULTICAST,              // Command, Adds a MAC multicast address to the reception filter.
              multi,                                    // Data 数据包存在这里面啦
              0);                                       // Flags
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_execAdapterCommand", "Failed to execute command");
    KS_closeDriver();
    return;
  }

  //------------------------------------------------------------------------------------------------------------
  // For data transfer between the async callbacks and the receive thread we use a pipe.
  // 用一个管道来进行异步回调与接收线程之间数据传输
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_createPipe(                              //创建管道
              &pAppPtr->hPipe_,                         // Pipe Handle
              "MyPacketRawEthernetMonitorPipe",         // Name管道名称
              sizeof(void*),                            // Item size, here pointer size
              100,                                      // Item count
              NULL,                                     // Object to signal
              0);                                       // Flags
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_createPipe", "Unable to create pipe!");
    KS_closeDriver();
    return;
  }

  //------------------------------------------------------------------------------------------------------------
  // Create an event object, which will be signalled when a packet arrives. 创建一事件,当有数据包到达时,有相应信号
  //每当有数据接收到时 有相应信号
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_createEvent(
              &pAppPtr->hEvent_,                        // Event handle
              "MyPacketRawEthernetMonitorEvent",        // Name of event
              0);                                       // Flags, here 0
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_createEvent", "Unable to create finish event!");
    KS_closeDriver();
    return;
  }

  //------------------------------------------------------------------------------------------------------------
  // Now create the thread.创建线程
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_createThread(                            //调用线程回调函数,当有信号(event产生),说明有数据,将数据从管道中读出
              _recvThread,                              // Thread function,调用回调函数,开始等待信号,有event信号,开始读出数据
              pAppPtr,                                  // Parameter to the thread
              NULL);                                    // Address of thread handle,
                                                        // not needed here
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_createThread", "Unable to create the thread!");
    KS_closeDriver();
    return;
  }

  //------------------------------------------------------------------------------------------------------------
  // For signalization we use a callback 回调函数
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_createCallBack(
              &pAppPtr->hCallBack_,                     // Address of callback handle 句柄地址
              _callBack,                                // Callback Routine 接收数据 将接收的数据放入管道中,并设置event,触发waitforevent,读出这里写入的数据
              pSysPtr,                                  // Reference parameter to the callback
              KSF_DIRECT_EXEC,                          // Flags, here kernel level in realtime context
              0);                                       // Priority
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_createCallBack", "Failed to create callback");
    KS_closeDriver();
    return;
  }

  //------------------------------------------------------------------------------------------------------------
  // Finally we start the packet receiver with KS_recvPackets.程序中没有KS_recvPackets的,源码注释错误。
  // The signalization object must be a callback create with DIRECT_EXEC.  // KS_installPacketHandler函数的作用是为网卡的某个事件(这里是收到数据包时触发的事件KS_PACKET_RECV)关联一个回调函数(pAppPrt->hCallBack),在事件触发时该回调函数将会被执行
  //------------------------------------------------------------------------------------------------------------

  pAppPtr->finished_ = false;                          // false表示线程中开始接收数据

  ksError = KS_installPacketHandler(                    // 安装数据包处理函数
              pAppPtr->hAdapter_,                       // Adapter handle
              KS_PACKET_RECV,                           // Event code 安装好用该函数进行数据包的接收,开始接收数据包
              pAppPtr->hCallBack_,                      // Callback handle,调用回调函数,将采集到的数据包的地址放入管道中
              KSF_RAW_ETHERNET_PACKET);                 // Flags Enables the raw ethernet packet mode for the handle,处理的是原始数据包
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_installPacketHandler", "Failed to install handler");
    KS_closeDriver();
    return;
  }

  inputTxt("Press <enter> to stop... ");
  outputTxt(" ");

/////以下为程序退出部分
  //------------------------------------------------------------------------------------------------------------
  // Set the event, so the thread can be finished. Before that, we set the variable ‘finished_‘ to true, so the
  // thread knows it should terminate.
  //------------------------------------------------------------------------------------------------------------

  pAppPtr->finished_ = true;                           //首先线程中接收到数据显示,然后线程关闭,以下是停止接收数据

  //------------------------------------------------------------------------------------------------------------
  // To stop the receiver, we set the Callback handle to NULL. 停止接收数据
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_installPacketHandler(
              pAppPtr->hAdapter_,                       // Adapter handle
              KS_PACKET_RECV,                           // Event code
              NULL,                                     // Callback handle句柄为null,停止接收数据
              KSF_RAW_ETHERNET_PACKET);                 // Flags
  if (ksError != KS_OK) {
    outputErr(ksError, "KS_installPacketHandler", "Failed to uninstall handler");
    KS_closeDriver();
    return;
  }

  ksError = KS_setEvent(pAppPtr->hEvent_);
  if (ksError != KS_OK)
    outputErr(ksError, "KS_setEvent", "Setting event failed!");
  waitTime(500 * ms);

  //------------------------------------------------------------------------------------------------------------
  // Display the adapter state 以下是显示适配器信息
  //------------------------------------------------------------------------------------------------------------

  KSAdapterState state;
  state.structSize = sizeof(KSAdapterState);
  ksError = KS_getAdapterState(                         //获取适配器信息函数
              pAppPtr->hAdapter_,                       // Adapter handle
              &state,                                   // Pointer to Buffer
              0);                                       // Flags
  if (ksError != KS_OK)
    outputErr(ksError, "KS_getAdapterState",
      "Querying the adapter state failed!");
  else {
    outputTxt(" ");
    outputDec(state.numPacketsSendOk,         "Number of packets sent successfully:             ", "");
    outputDec(state.numPacketsSendError,      "Number of packets failed to send:                ", "");
    outputDec(state.numPacketsSendARPTimeout, "Number of packets failed because of ARP timeout: ", "");
    outputDec(state.numPacketsWaitingForARP,  "Number of packets waiting for ARP:               ", "");
    outputDec(state.numPacketsRecvOk,         "Number of packets received successfully:         ", "");
    outputDec(state.numPacketsRecvError,      "Number of packets failed to receive:             ", "");
    outputTxt(" ");
  }

  //------------------------------------------------------------------------------------------------------------
  // Close the Adapter.
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_closeAdapter(                            //关闭适配器
              pAppPtr->hAdapter_);                      // Adapter handle
  if (ksError != KS_OK)
    outputErr(ksError, "KS_closeAdapter", "Unable to close Adapter!");

  //------------------------------------------------------------------------------------------------------------
  // Remove callbacks.
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_removeCallBack(
              pAppPtr->hCallBack_);                     // Callback handle
  if (ksError != KS_OK)
    outputErr(ksError, "KS_removeCallBack", "Unable to remove the callback!");

  //------------------------------------------------------------------------------------------------------------
  // Close the event object
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_closeEvent(
              pAppPtr->hEvent_);                        // Event handle
  if (ksError != KS_OK)
    outputErr(ksError, "KS_closeEvent", "Unable to close event!");

  //------------------------------------------------------------------------------------------------------------
  // Remove the data pipe
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_removePipe(
              pAppPtr->hPipe_);                         // Pipe handle
  if (ksError != KS_OK)
    outputErr(ksError, "KS_removePipe", "Unable to remove the pipe!");

  //------------------------------------------------------------------------------------------------------------
  // Remove the shared memory
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_freeSharedMem(
              pAppPtr);                                 // Application pointer
  if (ksError != KS_OK)
    outputErr(ksError, "KS_freeSharedMem", "Unable to remove shared memory!");

  //------------------------------------------------------------------------------------------------------------
  // At last we have to close the driver to free any allocated resources.
  //------------------------------------------------------------------------------------------------------------

  ksError = KS_closeDriver();
  if (ksError != KS_OK)
    outputErr(ksError, "KS_closeDriver", "Unable to close the driver!");

  waitTime(500 * ms);
  outputTxt("End of program ‘PacketRawEthernetMonitor‘.");
  outputTxt("Press <enter> to close.");
}

实时捕捉以太网原始数据包(PacketRawEthernetMonitor)----Kithara RTS工程源代码解析

时间: 2024-10-18 20:09:53

实时捕捉以太网原始数据包(PacketRawEthernetMonitor)----Kithara RTS工程源代码解析的相关文章

高速实时以太网----Kithara RTS

High speed Ethernet: The Packet Module 翻译注:本文主要讲述了如何使Kithara RTS操作以太网数据收发,Packet模块是krts提供的用于直接操作以太网的模块,使用该模块无需开发网卡驱动即可操作网卡收发数据,可以适用于大多数网卡,如intel,realtek的网卡等.可以用于满足实时收发原始数据包的情况要求,如开发自定义的工业实时以太网等.原文是kithara rts官方wiki的文档. 高速以太网:数据包模块 For industrial appl

配置一个逻辑CPU专用于实时任务----Kithara RTS工程源码分析

本文以windows实时拓展Kithara RTS安装目录下的smp文件夹内的DedicatedRealTimeTask项目为例,讲解使实时任务以独占一个逻辑CPU的方式运行,并实现任务间的同步. 目前多核计算机已经普及,多数的PC都是多核的.针对这种多核结构,我们设想把计算机划分为不同的硬件区间,其中一部分用于被实时任务专用,另一部分是被windows使用的,两者之间互不干扰,这样实时任务可以实现更好的实时性能.这种硬件划分,一般是按照物理CPU的核心数,即逻辑CPU的数量来配置的.可以配置一

EtherCAT ---- Kithara RTS

本文翻译了kithara官方文档,也加入了一些理解,暂时做得还不够完美,后续补充修正.2014.06.06 EtherCAT This tutorial describes the following topics using the EtherCAT API 本向导描述了使用EtherCAT API的功能说明 Creating a EtherCAT master assigned to a network adapter Creating slaves assigned to the mast

Shared Memory共享内存----kithara RTS

翻译注:共享内存是程序之间进行数据交互的最基本的方式,而由于windows和kithara rts本身为两个独立的系统,为了能够使两个不同系统之上的程序进行通信,那么就必须开辟一块内存区域用于数据共享.本文是对kithara rts官方原文进行的翻译,加入了本人的一些使用经验. Shared Memory(共享内存) What you need to know about Shared Memory(共享内存基本知识) In 32-bit and64-bit Windows operating

使用事件同步----Kithara RTS

Kithara RTS的事件机制,和windows编程中的事件机制比较像,如果有部分不明白,可以参考windows编程的这部分知识.事件在windows中是一种内核对象.事件主要用来实现任务之间的同步,同步并不是同时进行的意思,而是让整个软件的逻辑按照指定的顺序运行. 以下文章是拆字Kithara RTS官网,这里笔者给出翻译和部分编程经验. Synchronization with events Synchronization with events 事件同步 Events are very

多任务编程----Kithara RTS工程源码解析

本文以windows实时拓展Kithara RTS安装目录下的smp文件夹内的TaskSimple项目为例,解读Kithara RTS的实时多任务编程方法. 该项目只有一个工程TaskSimple,工程内的TaskSimple.cpp文件实现了主要功能,使用了Kithara RTS的kernel模块和Task模块 TaskSimple.cpp文件主要由5部分组成,共享内存结构体,三个任务回调函数,一个主函数runSample 共享内存结构体: //------ CallBackData ----

Kithara RTS的多任务编程

笔者理解:Kithara RTS的多任务编程主要用于内核实时程序开发中,其体系结构比较像一些嵌入式实时操作系统,如ucos,freertos等.笔者翻译了一部分内容,有一些内容看原文更好理解,因此没有翻译. Tasks The Multitasking Module offers task execution on kernel-level and user-level. On kernel-level a preemptive scheduling is implemented. The sc

使用PF_PACKET和SOCK_RAW发送自定义type以太网数据包

本文介绍使用PF_PACKET和SOCK_RAW发送自定义type以太网数据包,使用wireshare抓包可以获取到数据包,为Linux内核增加网络协议做铺垫. 先上码: #include <stdio.h> #include <stdlib.h> #include <unistd.h>           // close() #include <string.h>           // strcpy, memset(), and memcpy() #

Tutorial – Kithara RTS

Tutorial The Kithara ?RealTime Suite? (KRTS) is a real-time extension for Windows, which currently contains more than 20 different functional modules. In this tutorial, we try to explain every functional aspect, from starting with a simple program un