首先需要解决的是内核模式和用户模式之间的进程间通信(进程间通信,IPC)。
在各种IPC方法中,最适合这种设计的是netlink socket技术。
Netlink套接字首次出现在Linux 2.2内核中,并在2.4及更高版本中被广泛用作主内核和用户空间通信方法。
与系统调用,ioctl和proc文件系统等IPC方法相比,它具有简单易用,异步通信(适合大数据传输),无编译依赖(模块实现),支持组播,支持等优点。
内核启动会话等。
其中,“异步通信,无编译依赖,支持内核发起会话”。
这三点是该系统所需的关键特性,也是选择该技术的最重要原因。
Netlink套接字的通信基础是与进程相对应的标识符,通常将其定义为进程的ID。
当通信的一端处于中断过程中时,该标志为0。
当使用netlink套接字进行通信时,通信的两端都是用户模式进程,其用法类似于消息队列。
但是,通信的一端在一端被中断,并且使用方法不同。
Netlinksocket的最大特点是支持中断进程。
在内核空间中接收用户空间数据时,不需要用户启动内核线程。
相反,它通过另一个软中断调用用户指定的接收器功能,以便保证数据。
实时接收。
当netlink套接字用于内核空间和用户空间之间的通信时,用户空间创建方法类似于普通套接字,但内核空间创建方法不同。
使用内核模块中的netlink_kernel_create()函数创建套接字时,需要指定套接字函数。
然后,用户空间进程创建套接字并将通信ID(通常是进程的ID)发送到内核空间。
这样,内核空间可以在获得用户空间进程的通信标识后获得通信。
当从电子收款机的销售软件接收到并行打印机的打印请求时,内核侧并行打印模块在将数据发送到用户模式守护程序之后阻止打印请求过程。
并且,当且仅当接收到守护进程的返回数据时,才唤醒打印请求进程以完成打印。
如何实现打印过程的阻塞和觉醒是最后一个关键技术点。
因为电子收银机仅配备有一台打印机并且不需要复杂的互斥技术,所以这可以通过使用“简单睡眠”来实现。
Linux操作系统将设备视为文件。
每个Linux设备驱动程序都定义了一个file_operation结构。
结构的每个成员都是指向驱动程序模块中定义的函数的指针。
通过这些功能,文件可以打开,读取和写入。
等待操作。
因此,只要并行文件打印驱动程序模块的file_operation结构常量 - lp_fops的写入成员的值被lp_write替换为带有指向拦截功能的指针,就可以实时拦截并行打印机的打印操作。
这里需要实现两个关键功能:1)lp_write_from_kernellp_write_from_kernel函数实现在内核空间中打印缓冲区数据。
来自守护程序的修改后的打印数据保存在内核空间中,因此无法调用原始的lp_write函数进行打印。
具体实现可以基于lp_write,只要调用copy_from_user函数的位置被更改为调用memcpy函数即可。
2)lp_interceptlp_intercept函数用于替换lp_write,拦截并行端口打印驱动程序的写操作,实现对打印数据的拦截和修改:当电子收银机的销售软件调用并行端口的写入功能时打印驱动程序,发送写缓冲区的打印数据。
给守护进程;守护程序返回修改后的打印数据(附带税码),并通过调用lp_write_from_kernel打印它。