1
0
SWNote/Linux/Linux_IPC.md
2021-08-08 23:15:06 +08:00

289 lines
10 KiB
Markdown
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Linux Process Introduction
IPC ( Inter-Process Communication) , the **Software Program** is image for machine code and data which is stored in disks and can be executed it is a passive static entity, but the **Process** is program which executing under CPU, can apply and own the system resource . contain the program and info of current activity it is a dynamic entity.
The ways for Linux IPCs such like **Signal** , **Pipe /FIFO** , **Message queue** , **Semaphore**, **Share Memory** ect. more detail check the [following url](https://beej.us/guide/bgipc/).
![ipc1](../img/ipc_1.bmp)
![ipc2](../img/ipc_2.bmp)
## Signal
**Signals** are a limited form of [inter-process communication](https://en.wikipedia.org/wiki/Inter-process_communication) (IPC), typically used in [Unix](https://en.wikipedia.org/wiki/Unix), [Unix-like](https://en.wikipedia.org/wiki/Unix-like), and other [POSIX](https://en.wikipedia.org/wiki/POSIX)-compliant operating systems. A signal is an [asynchronous](https://en.wiktionary.org/wiki/asynchronous) notification sent to a [process](https://en.wikipedia.org/wiki/Process_(computing)) or to a specific [thread](https://en.wikipedia.org/wiki/Thread_(computer_science)) within the same process in order to notify it of an event that occurred.
When a signal is sent, the operating system interrupts the target process' normal [flow of execution](https://en.wikipedia.org/wiki/Control_flow) to deliver the signal. Execution can be interrupted during any [non-atomic instruction](https://en.wikipedia.org/wiki/Atomic_operation). If the process has previously registered a **signal handler**, that routine is executed. Otherwise, the default signal handler is executed.
Embedded programs may find signals useful for inter-process communications, as the computational and memory footprint for signals is small.
Signals are similar to [interrupts](https://en.wikipedia.org/wiki/Interrupt), the difference being that interrupts are mediated by the processor and handled by the [kernel](https://en.wikipedia.org/wiki/Kernel_(operating_system)) while signals are mediated by the kernel (possibly via system calls) and handled by processes. The kernel may pass an interrupt as a signal to the process that caused it (typical examples are [SIGSEGV](https://en.wikipedia.org/wiki/SIGSEGV), [SIGBUS](https://en.wikipedia.org/wiki/SIGBUS), [SIGILL](https://en.wikipedia.org/wiki/SIGILL) and [SIGFPE](https://en.wikipedia.org/wiki/SIGFPE)).
Each signal has a current disposition, which determines how the process behaves when it is delivered the signal.
( Note: 信号是Unix/Linux系统在一定条件下生成的事件。信号是一种异步通信机制进程不需要执行任何操作来等待信号的到达。信号异步通知接收信号的进程发生了某个事件然后操作系统将会中断接收到信号的进程的执行转而去执行相应的信号处理程序。)
### Related APIs
```C
#include <signal.h>
void (*signal (int, void (*)(int)))(int);
typedef void (*sighandler_t)(int);
/*如果signal()调用成功返回最后一次为安装信号signum而调用signal()时的handler值
失败则返回SIG_ERR。*/
sighandler_t signal(int signum, sighandler_t handler);
/* sigaction函数用于改变进程接收到特定信号后的行为。*/
int sigaction(int signum, const struct sigaction* act, struct sigaction* oldact);
int kill(pid_t pid, int sig);
int sigqueue(pid_t pid, int sig, const union sigval value);
```
### Sending Signals
```C
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
void new_op(int,siginfo_t*,void*);
int main(int argc,char**argv) {
struct sigaction act;
int sig;
sig=atoi(argv[1]);
sigemptyset(&act.sa_mask);
act.sa_flags=SA_SIGINFO;
act.sa_sigaction=new_op;
if(sigaction(sig,&act,NULL) < 0) {
printf("install sigal error\n");
}
while(1) {
sleep(2);
printf("wait for the signal\n");
}
}
void new_op(int signum,siginfo_t *info,void *myact) {
printf("receive signal %d", signum);
sleep(5);
}
```
Note:
| SIGABRT | 6 | Terminate (core dump) | Process abort signal |
| --------- | ---- | --------------------- | ------------------------------------------------- |
| SIGALRM | 14 | Terminate | Alarm clock |
| SIGBUS | N/A | Terminate (core dump) | Access to an undefined portion of a memory object |
| SIGCHLD | N/A | Ignore | Child process terminated, stopped, or continued |
| SIGCONT | N/A | Continue | Continue executing, if stopped |
| SIGFPE | N/A | Terminate (core dump) | Erroneous arithmetic operation |
| SIGHUP | 1 | Terminate | Hangup |
| SIGILL | N/A | Terminate (core dump) | Illegal instruction |
| SIGINT | 2 | Terminate | Terminal interrupt signal |
| SIGKILL | 9 | Terminate | Kill (cannot be caught or ignored) |
| SIGPIPE | N/A | Terminate | Write on a pipe with no one to read it |
| SIGPOLL | N/A | Terminate | Pollable event |
| SIGPROF | N/A | Terminate | Profiling timer expired |
| SIGQUIT | 3 | Terminate (core dump) | Terminal quit signal |
| SIGSEGV | N/A | Terminate (core dump) | Invalid memory reference |
| SIGSTOP | N/A | Stop | Stop executing (cannot be caught or ignored) |
| SIGSYS | N/A | Terminate (core dump) | Bad system call |
| SIGTERM | 15 | Terminate | Termination signal |
| SIGTRAP | 5 | Terminate (core dump) | Trace/breakpoint trap |
| SIGTSTP | N/A | Stop | Terminal stop signal |
| SIGTTIN | N/A | Stop | Background process attempting read |
| SIGTTOU | N/A | Stop | Background process attempting write |
| SIGUSR1 | N/A | Terminate | User-defined signal 1 |
| SIGUSR2 | N/A | Terminate | User-defined signal 2 |
| SIGURG | N/A | Ignore | High bandwidth data is available at a socket |
| SIGVTALRM | N/A | Terminate | Virtual timer expired |
| SIGXCPU | N/A | Terminate (core dump) | CPU time limit exceeded |
| SIGXFSZ | N/A | Terminate (core dump) | File size limit exceeded |
| SIGWINCH | N/A | Ignore | Terminal window size changed |
### Handle Signals
## Pipe
The **pipe** in Linux is identical in concept to the pipe in Unix, and is a core element of the Unix philosophy. The core idea that relates to pipes is you can pipeline simple Apps together and create a complex operation using pipes instead of needing large, complex applications.
(Note: 父进程和子进程之间或者两个兄弟进程之间可以通过系统调用建立起一个单向的通信管道。但是这种管道只能由父进程开建立对于子进程来说是静态的与生俱来的。管道两端的进程各自都将该管道视作一个文件。一个进程写另一个进程读。并且通过管道传递的内容遵循“先入先出”FIFO的原则。每个管道都是单向的需要双向通信时就要建立两个管道。)
### 1. Pipe == byte stream buffer in kernel
- Sequential (cant lseek())
- Multiple readers/writers difficult
### 2. Unidirectional
- Write end + read end
``` shell
ls | wc -l
```
![ipc_pipe](img/ipc_pipe.bmp)
##### Related basic APIs
```C
/*
filedes[0]: used only for read
filedes[1]: used only for write
*/
int filedes[1];
int pipe(int filedes[1]);
write(filedes[1], buf, count);
read(filedes[0], buf, count);
Close();
```
##### Sample:
```c
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
main() {
int pipe_fd[2];
pid_t pid;
char r_buf[100];
char w_buf[4];
char* p_wbuf;
int r_num;
int cmd;
memset(r_buf,0,sizeof(r_buf));
memset(w_buf,0,sizeof(r_buf));
p_wbuf=w_buf;
if(pipe(pipe_fd)<0)
{
printf("pipe create error\n");
return -1;
}
if((pid=fork())==0)
{
printf("\n");
close(pipe_fd[1]);
sleep(3);//确保父进程关闭写端
r_num=read(pipe_fd[0],r_buf,100);
printf("read num is %d the data read from the pipe is %d\n",r_num,atoi(r_buf));
close(pipe_fd[0]);
exit();
}
else if(pid>0)
{
close(pipe_fd[0]);//read
strcpy(w_buf,"111");
if(write(pipe_fd[1],w_buf,4)!=-1)
printf("parent write over\n");
close(pipe_fd[1]);//write
printf("parent close fd[1] over\n");
sleep(10);
}
}
```
## FIFO (named pipe)
- pipes (anonymous) can only be used by related processes
- FIFOs == pipe with name in file system
- Creation:
mkfifo(pathname, permissions)
- Any process can open and use FIFO
- I/O is same as for pipes
### Related basic APIs
```C
open(pathname, O_WRONLY/O_RDONLY);
#Open write/read end
open();
# locks until other end is opened Opens are synchronized
open(pathname, O_RDONLY | O_NONBLOCK);
# can be useful
```
#### Sample
```c
```
## Message Queue
#### Related basic APIs
```c
# Queue management (analogous to files)
# open/create MQ, set attributes
# flags (analogous to open()):
# O_CREAT create MQ if it doesnt exist
# O_EXCL create MQ exclusively
# O_RDONLY, O_WRONLY, O_RDWR just like file open
# O_NONBLOCK non-blocking I/O
# mode sets permissions
# &attr: attributes for new MQ
# NULL gives defaults
mqd = mq_open(name, flags [, mode, &attr]);
# close MQ
mq_close();
# remove MQ pathname
mq_unlink();
# I/O
# send message
mq_send();
# receive message
mq_receive();
# Other:
# set/get MQ attributes
mq_setattr(); / mq_getattr();
# request notification of msg arrival
mq_notify();
```
#### Sample:
```c
```
Socket
Semaphore
Shared Memory