Input Processing

来源:互联网 发布:matlab算矩阵乘法 编辑:程序博客网 时间:2024/06/08 15:32

Input processing is different from the output processing just described because the input is asynchronous. T**hat is, the reception of an input packet is triggered by a receive-complete interrupt to the Ethernet device driver, not by a system call issued by the process**. The kernel handles this device interrupt and schedules the device driver to run.
Ethernet Input
The ethernet device driver processes the interrupt and, assuming it signifies a normal receive complete condition, the data bytes are read from the device into an mbuf chain. In our example, 54 bytes of data are received and copied into a single mbuf: the 20-byte ip header, 8-byte udp header, and 26 bytes of data(the time and data on the server). Figure below shows the format of this mbuf.
这里写图片描述
This mbuf is a packet header(the m_pkthdr flag is set in m_flags) since it is the first mbuf of a data record. The len member in the packet header contains the total length of data and the rcvif. member contains a pointer to the interface structure corresponding to the received interface(chapter 3). We see that the recif member is used for received packets but not for output packets(figure 1.7 and 1.8)
The first 16 bytes of the data portion of the mbuf are allocated for an interface layer header, but are not used. Since the amout of data(54 bytes) fits in the remaining 84 bytes of the mbuf, the data is stored in the mbuf itself.
The device driver passes the mbuf to a general ethernet input routine which looks at the type field in the ethernet frame to determine which protocol layer should receive the packet. In this example, the type field will specify an ip datagram, causing the mbuf to be added to the ip input queue. Additionally, a software interrupt is scheduled to cause the ip input process routine to be executed. The device’s interrupt handling is then complete.
IP Input
Ip input is asynchronous and is scheduled to run by a software interrupt. The software interrupt is set by the interface layer when it receives an ip datagram on one of the system’s interface. When the ip input routine executes it loops, processing each ip datagram on its input queue and reutrning when the entire queue has been processed.
The ip input routine processes each ip datagram that it receives. It verifies the ip header checksum, processes any ip options, verifies that the datagram was delivered to the right host(by comparing the destination ip address of the datagram with the host’s ip addresses), and forwards the datagram if the system was configured as a router and the datagram is destined for some other ip address. If the ip datagram has reached its final destination, the protocol field in the ip header specifies which protocol’s input routine is called: icmp, igmp, tcp, or udp. In our example, the udp input routine is called to process the udp datagram.
UDP Input
The UDP input routine verifies the fields in the udp header and then determines whether or not a process should receive the datagram. In chapter 23 we discuss exactly how this test is made. A process can receive all datagrams destined to a specified UDP port, or the process can tell the kernel to restrict the datagrams it receives based on the source and destination IP addresses and source and destination port numbers.

In our example, the udp input routine starts at the global variable udb and goes through the linked list of udp protocol conntrol blocks, looking for one with a local port number(inp_lport) that matches the destination port number of the received udp datagram. This will be the pcb created by our call to socket, and the inp_socket member of this pcb points to the corresponding socket structure, allowing the received data to be queued for the correct socket.
In our example program we never specify the local port number for our application. We’ ll see in exercise 23.3 that a side effect of writting the first udp datagram to a socket that has no yet bound a local port number is the automatic assignment by the kernel of a local port number to that socket. That’s how the inp_lport member of the pcb for our socket gets set to some nonzero value.
Since this udp datagram is to be delivered to our process, the sender’s IP address and udp port number are placed into an mbuf, and this mbuf and the data are appended to the received queue for the socket. Figure below shows the two mbufs that are appended to the socket’s receive queue.
这里写图片描述
comparing the second mbuf on this chain(the one of type MT_DATA)with the mbuf in figure 1.10, the m_len and m_pkthdr.len members have both been decremented by 28(20 bytes for the IP header and 8 for the UDP header) and the m_data pointer has been incremented by 28. This effectively removes the ip and udp headers, leaving only the 26 bytes of data to be appended to the socketś receive queue.
The first mbuf in the chain contains a 16 byte internet socket address strucutrue with the senderś ip address and udp port number. Its type is mt_soname, similar to the mbuf in figure 1.6. This mbuf is created by the socket layer to return this information to the calling process through the recvfrom or recvmsg system calls. Even though there is room(16 bytes) in the second mbuf on this chain for this socket address sructure, it must be stored in its own mbuf since it has a different type(MT_SONAME versus MT_DATA).
The receiving process is then awakened. If the process is asleep waiting for data to arrive which is the scenario in our example, the process is marked as run-able for the kernel to schedule. A process can also be notified of the arrival of data on a socket by the select system call or with the sigio signal.
Process Input
Our process has been asleep in the kernel, blocked in its call to recvfrom, and the process now wakes up. The 26 bytes of data appended to the socket’s receive queue by the udp layer(the received datagram) are copied by the kernel from the mbuf into our programś buffer.
Notice that our program sets the fifth and sixth argument to recvfrom to null pointers, telling the system call that weŕe not interested in receiving the sender’s ip address and udp port number. This causes the recvfrom system call to skip the first mbuf in the chain(figure 1.11) , returning only the 26 bytes of data in the second mbuf. The kernel’s recvfrom code then releases the two mbufs in figure 1.11 and returns them to its pool of freee mbufs.

if ((n = recvfrom(sockfd, buff, BUFFSIZE, 0,                         (struct sockaddr *) NULL, (int *)NULL )) < 2)                perror("recvfrom error");
0 0
原创粉丝点击