Sending signals between processes
Here we use the kill command to transmit signals between processes.
For example, killing a process is also done by sending signals between processes:
#kill -9 pid
Correspondingly, if you want to send a signal, you need to register a signal processing function (similar to registering an interrupt service function), write a signal service function, and then write a function that sleeps all the time. The application signal.c code is as follows:
#include #include void mysignal_fun(int signum){ static int count = 0; printf("signal = %d, %d timesn", signum, count++); } int main(int argc, char **argv){ signal(SIGUSR1, mysignal_fun);// input: "kill -10(-USR1) pid" while(1) sleep(1000); return 0; } After running in the background through "&", use the process kill to pass the signal running in the background. #ps //Get PID #kill -USR1 signal_pid //pid obtained from ps From the above, we can see that in this method, we still have to manually obtain the pid number. In subsequent experiments, we will use functions to obtain the pid number. The running results are: # kill -USR1 752 signal = 10, 0 times # kill -USR1 752 signal = 10, 1 times # kill -10 752 signal = 10, 2 times # kill -USR1 752 signal = 10, 3 times # kill -10 752 signal = 10, 4 times The driver sends a signal to the application Key points: Register signal function Use the signal function to register the signal processing function in the application. Who sends the signal function sent from the driver Which function is this signal sent to? It is sent to the app. The app needs to tell the driver pid How to send kill_fasyn function The driver notifies the application when a key is pressed The method of sending signals from the driver to the application is similar to interrupts, and there are four problems: Register signal function Initialization signal function The driver sends a signal function This signal is sent by the driver to the application, that is, the application should tell the signal process PID number Step 1: Register signal processing function This step is to initialize the signal processing function through the signal() function, which is used to set the corresponding action for a certain signal. The declaration of the signal function is as follows: #include typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t sig_handler); The values of signum are shown in the following table: The handler describes the action associated with the signal and can take one of three values: SIG_IGN This symbol means to ignore the signal. For example: #include #include int main(int argc, char *argv[]){ signal(SIGINT, SIG_IGN); while(1) sleep(1000); return 0; } The SIGINT signal is generated by InterruptKey, usually CTRL + C or DELETE. When executing the above code, the program does not respond when pressing CTRL + C. That's right, if we want to end the program, we can press CTRL + to end it. When we press the CTRL + key combination, a SIGQUIT signal is generated, and this signal is not ignored. SIG_DFL This symbol indicates restoring the system default processing of the signal. If this processing function is not written, the system default operation will be executed by default. For example: #include #include int main(int argc, char *argv[]){ signal(SIGINT, SIG_DFL); while(1) sleep(1000); return 0; } At this time, you can press CTRL + C to terminate the process. Remove the sentence signal(SIGINT, SIG_DFL); and the effect is the same. The sighandler_t type function pointer is our signal processing function. Following the above two examples: #include #include typedef void (*signal_handler)(int); void signal_handler_fun(int signum) { printf("catch signal %dn", signum); } int main(int argc, char *argv[]) { signal(SIGINT, signal_hander_fun); while(1) sleep(1000); return 0; } In this way, we can execute a specific function when a signal comes. When ctrl+c is entered, the program will execute the signal processing function and output: catch signal 2 Since asynchronous communication is used, the signal is selected as SIGIO, and the read operation is performed in the signal service function (although the printing of my key value is completed in the interrupt function, I just print a read here to go through the motions): int fd; void my_fasyn_signal_fun(int signum){ unsigned char key_val; read(fd, &key_val, 1); printf("read!n"); } int main(int argc, char **argv) { signal(SIGIO, my_fasyn_signal_fun); fd = open("/dev/buttons", O_RDWR); while(1) sleep(1000); return 0; } Step 2: Drive the signal sending function The driver sends a SIGIO signal to the application via kill_fasync(&async, SIGIO, POLL_IN); and the application calls the response function installed by itself to handle it. async is a signal sequence structure, which needs to be defined and initialized (the initialization part is done in step 3, and it is assumed that it has been initialized here). POLL_IN means that data can be written. Therefore, the modification of the driver program in the sending part is very simple. It only needs to communicate in the interrupt function: static irqreturn_t button_irq(int irq, void *dev_id) { struct pin_desc *pindesc = (struct pin_desc *)dev_id; key_val = ((*(pindesc -> key_Register)) & (1<<(pindesc -> key_pin))) ? 0 : 1; if(key_val){ // printk("%d", pindesc -> key_num); } printk("%d ",key_val); printk("%dn",pindesc->key_num); ev_press = 1; /* Indicates that an interrupt has occurred*/ wake_up_interruptible(&button_waitq); /* wake up the sleeping process*/ kill_fasync(&button_async_queue, SIGIO, POLL_IN); // async signal to APP return IRQ_HANDLED; } step3: Initialization This is the most important step in asynchronous communication. Initialization consists of two parts: Initialization of button_async_queue (pit in step 2) You need to tell the kernel the PID of the application In general, the following three lines of commands can summarize these two parts: fcntl(fd, F_SETOWN, getpid()); // acquire the PID & tell kernal the PID oflags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, oflags | FASYNC); // change fasync_flag to call frv_fasync The function of fcntl() is to operate the characteristics of the file according to the file descriptor. Its definition is as follows: #include #include int fcntl(int fd, int cmd); int fcntl(int fd, int cmd, long arg); int fcntl(int fd, int cmd, struct flock *lock); fcntl() provides control over (file) descriptors. The parameter fd is the descriptor operated by the parameter cmd. fcntl can accept a third parameter int arg for the value of cmd. The cmd value can be taken as the following macro definition: Locking is an important function of fcntl! The asynchronous communication setting used here is just a flag to get the status of the setting file. After understanding the fcntl function, it is not difficult to analyze the functions of these three lines, as shown in the following figure: Initialization of button_async_queue The definition of this structure is as follows: static struct fasync_struct *button_async_queue; There is a special function in the kernel to initialize it: fasync_helper(). This function allocates memory and sets properties, and finally frees the things initialized by fasync_helper in the driver release. From the above analysis, the drv_fasync() function in the driver will be called during initialization, so the initialization operation of button_async_queue is performed in this function. It corresponds to the .fasync in the file structure, so the driver file is rewritten as follows: int button_drv_fasync(struct file *fd, struct file *filp, int on){ printk("dirver: Initialize fasyncn"); return fasync_helper(fd, filp, on, &button_async_queue); // Initialize button_async_queue } static struct file_operations button_drv_fops = { .owner = THIS_MODULE, /* This is a macro that pushes to the __this_module variable that is automatically created when compiling the module*/ .open = button_drv_open, .read = button_drv_read, .release = EINTkey_close, .poll = botton_drv_poll, .fasync = button_drv_fasync, }; The driver sends a signal to the application. driver #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include #define DEV_NAME "button_drv" // device name static struct class *buttondrv_class; static struct class_device *buttondrv_class_dev; static DECLARE_WAIT_QUEUE_HEAD(button_waitq); /* Interrupt event flag, the interrupt service routine sets it to 1, and third_drv_read clears it to 0 */ static volatile int ev_press = 0; /* Key value: when pressed, 0x01, 0x02, 0x03, 0x04 */ /* Key value: when released, 0x81, 0x82, 0x83, 0x84 */ static unsigned char key_val; static struct fasync_struct *button_async_queue; volatile unsigned long *gpfcon = NULL; volatile unsigned long *gpfdat = NULL; volatile unsigned long *gpgcon = NULL; volatile unsigned long *gpgdat = NULL; struct pin_desc{ volatile unsigned long *key_Register; int key_pin; int key_num; }; struct pin_desc pins_desc[4] = { {0x01, 0, 1}, {0x02, 2, 2}, {0x03, 3, 3}, {0x04, 11, 4}, }; static irqreturn_t button_irq(int irq, void *dev_id) { struct pin_desc *pindesc = (struct pin_desc *)dev_id;
Previous article:S3C2440 development board practice (11): synchronization and mutual exclusion
Next article:S3C2440 development board practice (9): poll mechanism
Recommended ReadingLatest update time:2024-11-23 03:00
- Naxin Micro and Xinxian jointly launched the NS800RT series of real-time control MCUs
- How to learn embedded systems based on ARM platform
- Summary of jffs2_scan_eraseblock issues
- Application of SPCOMM Control in Serial Communication of Delphi7.0
- Using TComm component to realize serial communication in Delphi environment
- Bar chart code for embedded development practices
- Embedded Development Learning (10)
- Embedded Development Learning (8)
- Embedded Development Learning (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Intel promotes AI with multi-dimensional efforts in technology, application, and ecology
- ChinaJoy Qualcomm Snapdragon Theme Pavilion takes you to experience the new changes in digital entertainment in the 5G era
- Infineon's latest generation IGBT technology platform enables precise control of speed and position
- Two test methods for LED lighting life
- Don't Let Lightning Induced Surges Scare You
- Application of brushless motor controller ML4425/4426
- Easy identification of LED power supply quality
- World's first integrated photovoltaic solar system completed in Israel
- Sliding window mean filter for avr microcontroller AD conversion
- What does call mean in the detailed explanation of ABB robot programming instructions?
- STMicroelectronics discloses its 2027-2028 financial model and path to achieve its 2030 goals
- 2024 China Automotive Charging and Battery Swapping Ecosystem Conference held in Taiyuan
- State-owned enterprises team up to invest in solid-state battery giant
- The evolution of electronic and electrical architecture is accelerating
- The first! National Automotive Chip Quality Inspection Center established
- BYD releases self-developed automotive chip using 4nm process, with a running score of up to 1.15 million
- GEODNET launches GEO-PULSE, a car GPS navigation device
- Should Chinese car companies develop their own high-computing chips?
- Infineon and Siemens combine embedded automotive software platform with microcontrollers to provide the necessary functions for next-generation SDVs
- Continental launches invisible biometric sensor display to monitor passengers' vital signs
- GD32-colibri-F350RX unboxing spray
- Share a cheap xilinx high-speed downloader
- Looking for AMS1117-3.3V low power alternative
- Radio Frequency Technology Accelerates 3G Application
- [SAMR21 new gameplay] 17. Download python firmware
- error: no matching function for call to 'xxx'
- LLC circuit dead time
- Reconstructing the antenna design solution for mobile devices in the 5G era
- What exactly are those “special pads” on PCB boards used for?
- CC2640 power configuration modification