void NeedSpawn(struct socket *sock)
{ //InitCount表示已经创建的但是还没有接受连接的子线程;AcceptCount表示正在accept过程中的子线程
while (atomic_read(&InitCount)+atomic_read(&AcceptCount) {
kernel_thread(khttpd_child,sock,0);
atomic_inc(&InitCount);
}
}
int khttpd_child(void *TMP)
{
struct socket *sock,*newsock;
struct sock *sk;
int error;
struct proto_ops *ops;
char *Buffer;
size_t BufLen;
struct http_time *httptime;
current->session = 1;
current->pgrp = 1;
current->state |= TASK_WAKE_ONE;
sprintf(current->comm,"khttpd - request");
sock = (struct socket*)TMP;
sk = sock->sk;
sk->nonagle = 1;
sk->linger = 1;
...
error=0;
Buffer = (char*) get_free_page(GFP_KERNEL);
httptime = kmalloc(sizeof(struct http_time),GFP_KERNEL);
atomic_dec(&InitCount);
...
memset(httptime,0,sizeof(struct http_time));
while (1==1)
{
if (atomic_read(&AcceptCount)>KHTTPD_MAXACCEPT) //判断是否拥有太多的子内核线程,其实就是http处理线程
break; //如果太多就不再启动本次的了
newsock = sock_alloc();
newsock->type = sock->type;
sock->ops->dup(newsock,sock);
ops = newsock->ops;
atomic_inc(&AcceptCount);
error = ops->accept(sock,newsock,0);
atomic_dec(&AcceptCount);
...
error=HandleIncommingConnection(newsock,Buffer,&BufLen,httptime); //实际处理客户端请求
if (error<0)
{
if (HandleUserSpace(newsock,Buffer,BufLen)<0) //如果内核处理出错,那么返回给用户空间去处理,也就是交给用户空间的web服务器
ErrorXXX(newsock,-error);
}
...
}
free_page((unsigned long)Buffer);
kfree(httptime);
return 0;
}
int HandleIncommingConnection(struct socket *sock, char *Buffer, size_t *BufLen,struct http_time *httptime)
{
struct msghdr msg;
struct iovec iov;
int len;
mm_segment_t oldfs;
struct http_header Head;
...//数据初始化
oldfs = get_fs(); set_fs(KERNEL_DS);
len = sock_recvmsg(sock,&msg,1024,0);
set_fs(oldfs);
...//出错处理,出错返回500
/* Check if the request is finished */
if ((len<4))
{
int len2;
...//数据初始化
len2 = sock_recvmsg(sock,&msg,1024,MSG_DONTWAIT);
set_fs(oldfs);
interruptible_sleep_on_timeout(&sock->wait,HZ*5);
if (len2>0)
len+=len2;
}
Buffer[len+1]=0;
*BufLen = len;
ParseHeader(Buffer,len,&Head); //解析头部
if (Head.FileName[0]!=0)
{
struct file * filp;
...//出错处理,出错返回403
filp = filp_open(Head.FileName,00,O_RDONLY); //打开客户端需要的文件
...//出错处理,出错返回404
if ((filp!=NULL)&&(filp->f_dentry!=NULL))
{
int FileLength,Permission;
char *Header;
...//权限判定,访问控制功能
FileLength = (int)(filp->f_dentry->d_inode->i_size);
if (Head.IMS[0]>0)
{
time_t TIME;
TIME=mimeTime_to_UnixTime(Head.IMS);
...//出错处理,出错返回304
}
Header = HTTPHeader(Head.FileName,FileLength,filp->f_dentry->d_inode->i_mtime,httptime);
...//出错处理,出错返回500
khttp_copy_filp_to_sock(filp,sock,FileLength,Header);
if (Header)
kfree(Header);
fput(filp);
}
return 200;
}
return -404;
}
注 意以上除了成功返回200之外,别的出错码都不是返回给客户端的,而是在khttpd_child经过判断出错后,交给用户空间再处理一次,因为内核只负 责静态页面的推送而不管别的,因此内核处理不了而出错不代表用户空间的web服务器就处理不了,于是交给khttpd_child中调用的 HandleUserSpace:
int HandleUserSpace(struct socket *sock, char *ReceivedSoFar, size_t length)
{
struct msghdr msg;
struct iovec iov;
int len;
mm_segment_t oldfs;
char *Buffer;
struct socket *clientsock;
/* struct sockaddr_un name;*/
struct sockaddr_in sin;
int error,count=0;
Buffer = (char*) get_free_page(GFP_KERNEL);
...//出错处理,真的返回500
error = sock_create(PF_INET,SOCK_STREAM,IPPROTO_TCP,&clientsock);
if (error<0)
printk("Error during creation of socket; terminating\n");
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); //注意,向回环接口也就是127.0.0.1接口发送客户端请求,这样写入的请求就会被用户空间的web服务器受到,某种意义上,这个khttpd更像 是一个web代理,在客户端和用户空间真正的web服务器之间的代理。
sin.sin_port = htons(KHTTPD_CLIENTPORT); //注意,这个端口一定要在用户空间的web服务器上配置
error = clientsock->ops->connect(clientsock,(struct sockaddr*)&sin,sizeof(sin),0); //连接真正的用户空间的web服务器,比如apache
...
SendBuffer(clientsock,ReceivedSoFar,length); //把客户端的请求发送真正的用户空间web服务器
len=1;
while ((len>0)&&(count<10000)) //这个循环中可以看出内核的khttpd就是一个代理
{
...//数据缓冲区初始化
oldfs = get_fs(); set_fs(KERNEL_DS);
len = sock_recvmsg(sock,&msg,4096,MSG_DONTWAIT); //继续从客户端浏览器接受请求
set_fs(oldfs);
...
if (len>0)
SendBuffer(clientsock,Buffer,len); //如果有请求则继续向用户空间的web服务器转发
if (len<-100)
break;
...数据缓冲区初始化
oldfs = get_fs(); set_fs(KERNEL_DS);
len = sock_recvmsg(clientsock,&msg,4096,MSG_DONTWAIT); //接受用户空间web服务器的回应
set_fs(oldfs);
if (len>0)
SendBuffer(sock,Buffer,len); //将回应转发给客户端
...
count++;
}
sock_release(clientsock);
free_page((unsigned long)Buffer);
return 0;
}
注 意,这个函数返回了,如果返回值是负数,那么就说明用户空间的web服务器也处理不了,那就是真的发生了错误,于是就要真的进行错误返回了,其实就是调用 ErrorXXX(newsock,-error)函数,此时从HandleIncommingConnection返回的错误码还保留着:
void ErrorXXX(struct socket *sock, int Error)
{
if (Error == 404)
{
Error404(sock);
return;
}
...
}
void Error404(struct socket *sock)
{
char Message[]=
"HTTP/1.0 404 File Not Found\r\nServer: KHTTPD/0.0\r\nContent-type: text/html\r\n\r\nFILE NOT FOUND!!";
SendBuffer(sock,Message,sizeof(Message)); //真正向客户端返回错误码。
}
以 上就是khttpd的大致框架了,很有意思的就是它在内核中的作用就是客户端和用户空间web服务器的代理,虽然它作为一个以加速为目的的web服务来说 已经不再需要,但是我倒是觉得它可以作为一个很好的过滤系统经过改进后继续存在,就像netfilter一样,但是netfilter拦截五元素很方便, 虽然也可以解析数据包的具体内容,但是那很耗时,而且大多数的运行netfilter的接收过滤的上下文都是软中断上下文,因此更加不确定,更不适合做像 从sk_buff中解析用户数据并且判定那些事,因此khttpd的框架可以作为很好的用户数据过滤框架在内核中存在,新的框架不再仅仅监听端口为80的 web服务,而是可以监听所有的端口,只要用户建立一个服务器套接字,那么都可以选择将此套接字加入到过滤列表中,可以通过ioctl调用很容易做到这一 点。然后可以在内核配置一张过滤表,存放每一个端口的过滤策略,这个表的格式可以参照iptables的结构设计,如果通过的话,可以将请求直接转发给用 户空间的套接字,如果没有通过验证,那么记录审计信息后返回错误。如此的设计可能没有必要,因为linux内核可能压根就不想管像用户数据那么具体的事 情,如果你非要往内核加入这个框架的话,那么过滤的策略的设置将是一场噩梦,毕竟用户数据是一个很庞大很不具体的概念,难道过滤敏感词汇吗?如果是的话, 估计敏感词汇都存在内核瞬间内存就满了,众口难调啊,即使这个想法不被应用了内核主线,那么很可能可以满足某个老板的需求,我们公司就在做一个网页防篡改 系统,我想我可以借鉴一下这个khttpd框架,然后改改,实现我们linux版的网页防篡改系统。
linux从来不在内核提供个别应用才会用到的策略,不允许策略污染机制,呵呵,即使在2.4内核时策略(khttpd)真的污染了那么一点点机制,然而 随着2.6内核的放出,仅有的污点还是被驱赶了,因为linux内核靠更好的机制就可以给用户空间提供更好的舞台,而想在这个舞台演得好需要成为好的舞者,这难道给用户编程带来了挑战,其实程序员需要的不是什么技巧,而是unix编程的哲学思想。
相关推荐
kHTTPd和其它web服务器的不同之处在于其是作 为内核的一部分运行在Linux的内核中(可以看成是一个设备驱动)。KHTTPd仅仅处理静态(基于静态文件的)的web页面,而将所有的对于非静态内容的请求传递给正常的运行于用户...
windows 下驱动层程序,创建虚拟磁盘,驱动层的web服务器,内存文件系统 filedisk-17.zip genromfs-0.5.1.tar.gz khttpd-2.zip rawritent.zip romfs-15.zip romfsimg.zip
如果要试验现在仍处于实验阶段的功能,比如khttpd、IPv6等,就必须把该项选择为Y了;否则可以把它选择为N。在Linux的世界里,每天都有许多人为它发展支持的driver和加强它的核心。但是有些driver还没进入稳定的阶段...
99-智慧园区数据平台方案.pptx
Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。
网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。系统化是必要的,设计网上系统不仅会节约人力和管理成本,还会安全保存庞大的数据量,对于信息的维护和检索也不需要花费很多时间,非常的便利。 网上系统是在MySQL中建立数据表保存信息,运用SpringBoot框架和Java语言编写。并按照软件设计开发流程进行设计实现。系统具备友好性且功能完善。 网上系统在让售信息规范化的同时,也能及时通过数据输入的有效性规则检测出错误数据,让数据的录入达到准确性的目的,进而提升数据的可靠性,让系统数据的错误率降至最低。 关键词:vue;MySQL;SpringBoot框架 【引流】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes
Excel工资条模板是一种预先设计好的电子表格文件,主要用于生成和打印员工的工资单,让员工清楚了解自己的工资组成和扣款详情。模板通常包含了以下几个关键部分: 1. **员工信息区**: - 姓名 - 员工编号/工号 - 部门 - 职位 2. **工资构成区**: - 基本工资 - 岗位工资 - 绩效奖金 - 加班工资 - 其他补贴(如交通补贴、餐补、全勤奖等) - 各项津贴(如高温补贴、取暖费等) - 其他应发收入(如年终奖、提成、福利等) 3. **扣款项目区**: - 社保扣款(养老保险、医疗保险、失业保险、工伤保险、生育保险) - 住房公积金 - 个人所得税 - 其他扣款(如迟到、旷工、违规罚款等) - 预借还款(如有) 4. **工资结算区**: - 应发工资总额 - 扣款总额 - 实发工资 5. **备注栏**: - 用于标注本月工资的特殊情况说明,如请假、调休、加班等情况。 6. **签名栏**: - 供员工确认工资数额无误后签名,也可以
29-【智慧城市与政府治理分会场】10亿大数据助推都市治理-30页.pdf
网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。系统化是必要的,设计网上系统不仅会节约人力和管理成本,还会安全保存庞大的数据量,对于信息的维护和检索也不需要花费很多时间,非常的便利。 网上系统是在MySQL中建立数据表保存信息,运用SpringBoot框架和Java语言编写。并按照软件设计开发流程进行设计实现。系统具备友好性且功能完善。 网上系统在让售信息规范化的同时,也能及时通过数据输入的有效性规则检测出错误数据,让数据的录入达到准确性的目的,进而提升数据的可靠性,让系统数据的错误率降至最低。 关键词:vue;MySQL;SpringBoot框架 【引流】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes
5G通信行业、网络优化、通信工程建设资料。
299-教育数据资产管理平台及配套解决方案.pptx
abababababababab
STM32学习软件编程资料,STM32F103C8单片机经典外设应用设计实例软件源代码,KEIL工程文件,可供学习参考。
5G通信行业、网络优化、通信工程建设资料。
5G通信行业、网络优化、通信工程建设资料
3M 轨道砂光机精英系列说明书
网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。系统化是必要的,设计网上系统不仅会节约人力和管理成本,还会安全保存庞大的数据量,对于信息的维护和检索也不需要花费很多时间,非常的便利。 网上系统是在MySQL中建立数据表保存信息,运用SpringBoot框架和Java语言编写。并按照软件设计开发流程进行设计实现。系统具备友好性且功能完善。 网上系统在让售信息规范化的同时,也能及时通过数据输入的有效性规则检测出错误数据,让数据的录入达到准确性的目的,进而提升数据的可靠性,让系统数据的错误率降至最低。 关键词:vue;MySQL;SpringBoot框架 【引流】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes
2023年亚太杯A题附件一,苹果图像数据集
5G通信、网络优化与通信建设