Tag Archives: Kernel

C++: Implementation of multi-channel IO transfer with select

Basic idea of select

Set LFD as port reuse

The file descriptors that need to be monitored are sent to the kernel for listening through select. When an event occurs, the number of events is returned through select. Then scan the set of file descriptors one by one to process the event.

Include file:

< sys/select.h>

The function structure of select is as follows:

int select(int nfds, fd_ set * readfds, fd_ set *writefds, fd_ set *exceptfds, struct timeval *timeout);

Parameter description

fd_ Set: the structure of file descriptor set. It is a 1024 bitmap. 0 means that there is no event and 1 means that there is an event. The converted format is:
typedef struct
{
long int__ fds_ bits[1024/(8*8))];
}
NFDS: the maximum number of file descriptors being monitored is + 1
readfds: read set is an incoming and outgoing parameter. The incoming parameter is the set of file descriptors that need to be read and monitored, and the outgoing parameter is the changed file descriptor<
writefds: write file descriptor (same as above, incoming and outgoing parameters)
execptfds: exception file descriptor (same as above, incoming and outgoing parameters)
timeout:
0: no blocking, return immediately after scanning
greater than 0: blocking waiting time is long, return immediately when no event occurs before arrival time
null: permanent blocking wait event
Return:
– 1: listening failure
greater than 0: number of events

Correlation bit operation

1. Remove FD from set
void FD_ CLR(int fd,set *set);
2. Judge whether the descriptor is in the set
2_ ISSET(int fd,fd_ set *set);
3. Put descriptors into the set
void FD_ SET(int fd,fd_ Set * set)
4. Empty set
void FD_ ZERO(fd_ set *set)

Advantages and disadvantages of select

Advantages: cross platform, supported on both windows and Linux
disadvantages: it involves copying back and forth between user area and kernel area. When there are many links but few active users, the efficiency is low, and the maximum number of listeners can not exceed 1024.

Select code

Insert code snippet here
#include<sys/types.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>	
#include<netinet/in.h>
#include<ctype.h>
#include<sys/socket.h>
#include<sys/select.h>

#include<iostream>
#include<string>

using namespace  std;
int main()
{
    /*1.create socket*/
    int lfd=socket(AF_INET,SOCK_STREAM,0);
    if(lfd<0)
    {
        perror("socket error!");
        return -1;
    }
    /*Setting up port multiplexing*/
    int opt=1;
    setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(int));
    /*Initialize server-side address structure*/
    struct sockaddr_in  sevr;
    bzero(&sevr,sizeof(sevr));
    sevr.sin_family=AF_INET;
    sevr.sin_port=htons(9090);
    sevr.sin_addr.s_addr=htonl(INADDR_ANY);

    /*Binding socket address structure*/
    int ret=bind(lfd,(sockaddr *)&sevr,sizeof(sockaddr));
    if(ret<0)
    {
        perror("bind error!");
        return -1;
    }
    /*Listening to events*/
    int re= listen(lfd,128);

    /*Create a collection of listened read events*/
    fd_set readfds;
    fd_set tmpfds;

    /*Initialization*/
    FD_ZERO(&readfds);
    FD_ZERO(&tmpfds);
    /*Adding file descriptors to the read event set*/
    FD_SET(lfd,&readfds);
    int maxfd=lfd+1;
    int cfd;
    while(1)
    {
        tmpfds=readfds;
        /*Give the event descriptors in the collection to the kernel to listen */
        /* Listening range, max file descriptors + 1*/
        int nready=select(maxfd+1,&tmpfds,NULL,NULL,NULL);
        cout<<nready<<endl;
        if(nready<0)
        {
            /*Event Terminal*/
            if(errno==EINTR)
                continue;
	    cout<<"select error"<<endl;
            break;
        }

        /*There is a client connection request*/
        if(FD_ISSET(lfd,&tmpfds))
        {
            cfd=accept(lfd,NULL,NULL);
            if(cfd<=0)
            {
                cout<<"accept error"<<endl;
                return -1;
            }
            /*Add cfd to the listener set */
            FD_SET(cfd,&readfds);

            /*Modify the value of maxfds*/
            if(maxfd<=cfd)
            {
                maxfd=cfd;
            }
             /* Only listen events, no read content events*/
            if(--nready==0)
            {
                cout<<"continue"<<endl;
                continue;
            }
        }

        /*Polling to find out the descriptors of read events*/
        for(int i=0;i<=maxfd;i++)
        {
            cout<<i <<endl;
            if(FD_ISSET(i,&tmpfds))
            {
                cout<<"is in cfds"<<endl;
                char buf[1024]={0};
                int n=read(i,buf,sizeof(buf));
                if(n<=0)
                {
                    /*close*/
                    cout<<"read error"<<endl;
                    close(i);
                    /*dele*/
                    FD_CLR(i,&readfds);
                }
                else
                {
                    cout<<buf<<endl;
                    for(int k=0;k<n;k++)
                    {
                        buf[k]=toupper(buf[k]);
                    }
                    write(i,buf,n);
                }

            }
        }
    }

    close(lfd);
    close(cfd);
    return 0;
}

Nucleus plus protection mechanism (based on ARM processor)

(Nucleus Plus is a non open source operating system, only limited code is provided for reference)

1. Nucleus plus protection mechanism

Nucleus plus kernel uses TC for small code protection_ Protect only in TC_ The interrupt is only turned off during protect operation, so the interrupt response and scheduling of Nucleus Plus kernel is more timely than that of μ C/os-iii and ThreadX; mutex is only used for applications (mutex between threads).

TC_ Protect contains two members. One record gets TC_ Thread pointer TC of protect_ tcb_ Another mark is whether there is a thread waiting for TC_ The variable TC of protect_ thread_ waiting。

2、TC_ Protect acquisition (TCT)_ Protect)

Off interrupt

1624         MRS     r1,CPSR                     // Pickup current CPSR
1625         ORR     r1,r1,#LOCKOUT              // Place lockout value in
1626         MSR     CPSR_cxsf,r1                     // Lockout interrupts

Check TC_ Is protect occupied (check TC_ tcb_ Whether the pointer is empty; if it is not occupied, jump to TCT_ Protect_ Available, set TC_ tcb_ The pointer is the pointer of the current thread, and you can turn on the interrupt again. If it is occupied, you will check whether it is occupied. It is similar to the spin lock of Linux kernel, but Nucleus Plus is single core, so the current thread needs to switch out of the CPU.)

1632 TCT_Protect_Loop:
1633         LDR     r1,[r0, #0]                 // Pickup protection owner field
1634         CMP     r1,#0                       // Is there any protection?
1635         BEQ     TCT_Protect_Available       // If NU_NULL, no current protection

Set TC_ thread_ Waiting is 1 (indicates that there is a thread waiting for TC)_ PROTECT)

1642         MOV     r2,#1                       // Build thread waiting flag
1643         STR     r2,[r0, #4]                 // Set waiting field

If TC_ Protect is occupied. Save the context of the current thread and call TCT_ Schedule_ Protected scheduling takes up TC_ Thread of protect (the current thread is the thread with the highest priority and occupies the TC_ The thread of protect has a lower priority. If you don’t actively schedule the thread of low priority, the thread of low priority will never be able to execute, TC_ Protect will never be released)

1648         STR     r0,[sp, #-4]!               // Save r0 on the stack
1649         STR     lr,[sp, #-4]!               // Save lr on the stack
1650         MOV     r0,r3                       // Place current thread into r0
1651         BL      TCT_Schedule_Protected      // Call routine to schedule the
1652                                             // owner of the thread

3、TC_ Protect release (TCT)_ Unprotect)

Check TC_ thread_ Whether waiting is 0. If it is 0, no thread is waiting for TC_ Otherwise, there are higher priority threads waiting for TC_ PROTECT(TC_ There is no interrupt in the process from the acquisition of protect to the release of TC_ Before protect, a higher priority thread may be ready to apply for the same TC_ If there is no thread waiting for TCT_ Unprotect, simply set TC_ tcb_ If the pointer is empty, turn on the interrupt; otherwise, call TCT_ Control_ To_ System rescheduling (waiting for TCT)_ The unprotected thread may not be the thread with the highest priority at this time, but the scheduler obtains the highest priority ready thread for execution;

TCT_ Control_ To_ System checks whether the time slice of the current thread is used up; if it is not used up, it will continue to execute the current thread (to avoid frequent thread switching, so TCT is called)_ Control_ To_ TC is not set before system_ tcb_ If the time slice is used up, set TC_ tcb_ Pointer is empty, TC_ thread_ Waiting is 0 (wait for TC before)_ The thread released by protect is no longer waiting for TC_ Protect. After the thread is scheduled, it returns to TCT_ Protect_ Loop is equivalent to calling TCT again_ Protect, reacquire lock (wait for TC for some reason)_ Thread released by protect is suspended, TC_ thread_ The waiting flag cannot always be set to 1, otherwise other threads will release TC_ When protect, it will mistakenly think that there is a thread waiting for TC_ Protect release), call TCT_ Schedule selects the highest priority ready thread for execution. (thread scheduling reference) https://blog.csdn.net/arm7star/article/details/105565769 “NucleusPLUS interrupt processing (based on ARM processor)”

1783         LDR     r2,[r0, #4]                 // Pickup thread waiting flag
1784         CMP     r2,#0                       // Are there any threads waiting?
1785         BEQ     TCT_Not_Waiting_Unpr        // If not, just release protection

4. Summary

To some extent, the protect mechanism of nucleus plus can be regarded as priority inversion, that is, high priority threads give up CPU to low priority threads. Nucleus plus does not implement dynamic priority, and protect avoids deadlock.

 

make modules_ Install compiles the kernel driver as a module, and the location of. Ko file in the root file

Based on the kernel Documentation: Documentation/kbuild/modules. TXT: Building External modules section 5 describes position description
can be determined as follows:

--- 5.1 INSTALL_MOD_PATH

	Above are the default directories but as always some level of
	customization is possible. A prefix can be added to the
	installation path using the variable INSTALL_MOD_PATH:

		$ make INSTALL_MOD_PATH=/frodo modules_install
		=> Install dir: /frodo/lib/modules/$(KERNELRELEASE)/kernel/

	INSTALL_MOD_PATH may be set as an ordinary shell variable or,
	as shown above, can be specified on the command line when
	calling "make." This has effect when installing both in-tree
	and out-of-tree modules.

--- 5.2 INSTALL_MOD_DIR

	External modules are by default installed to a directory under
	/lib/modules/$(KERNELRELEASE)/extra/, but you may wish to
	locate modules for a specific functionality in a separate
	directory. For this purpose, use INSTALL_MOD_DIR to specify an
	alternative name to "extra."

		$ make INSTALL_MOD_DIR=gandalf -C $KDIR \
		       M=$PWD modules_install
		=> Install dir: /lib/modules/$(KERNELRELEASE)/gandalf/

Error kernel restart: restart failed was reported in the background of jupyter notebook

after successful installation by PIP install jupyter In the CMD window, run the jupyter notebook, and it was found that the left side of the code In [] changed to In [*], and the error was reported In the CMD window as follows:

KernelRestarter: restart failed. Kernel restart failed

solution: PIP install –upgrade ipykernel will upgrade it can run normally, although it will prompt you prompt toolkit version should be between 1.0 and 2.0, but it does not affect the operation of prompyter notebook. In the upgrade process, the main updated module is the prompt_toolkit, it seems that because the version of this module is too low, it leads to

WSL 2 needs to update its kernel components

welcome to my blog

problem description: open win10 terminal display: WSL 2 needs to update its kernel components;

download the upgrade package of WSL2 Linux kernel from Microsoft, download the link, as shown in the figure below, click “this link” to download

install the update package, all the way next, without any additional options