先大概的总结一下,及基本的用法,其中每一个,展开都可以写一篇文章的
- 匿名管道(Pipe)
- 命名管道(Named pipe)
- 消息队列 (Message Queues)
- 信号 (Signal)
- 信号量 (Semaphore)
- 共享内存 (Shared Memory)
- Socket
1.1匿名管道(Pipe)
//1.1匿名管道通讯
#include
#include
#include
int main(int argc, char const *argv[])
{
pid_t my_pid = getpid();
char buffer[256];
memset(buffer, 0, sizeof(buffer));
int fildes[2];//fildes[0]接受数据,fildes[1]发送数据
if (-1 == pipe(fildes)) {
printf("创建管道失败\n");
return 1;
}
int pid = fork();
printf("fork result:%d\n",pid);
if (pid == 0) { //子进程
my_pid = getpid();//更新当前pid
printf("子进程:%d: sleep 5s\n",my_pid);
sleep(5);
int nbyte = write(fildes[1], "你好呀,我是子进程", strlen("你好呀,我是子进程"));
printf("子进程:%d:写了%d字节\n",my_pid, nbyte);
close(fildes[1]);
} else {
my_pid = getpid();//更新当前pid
read(fildes[0], buffer, sizeof(buffer));
printf("父进程:%d:读了内容=>[%s]\n",my_pid, buffer);
close(fildes[0]);
printf("父进程:%d:sleep 5s\n",my_pid);
sleep(5);
}
return 0;
}
Res:
terence@k8s-master:/mydata/linux$ ./a.out
fork result:55440
fork result:0
子进程:55440
子进程:55440:写了27字节
父进程:55439:读了内容=>[你好呀,我是子进程]
父进程:55439
//与此同时另一个ssh窗口查看进程(因为代码中故意sleep了)
terence@k8s-master:/mydata/linux$ ps -ef | grep 'a.out'
terence 55439 97831 0 15:21 pts/0 00:00:00 ./a.out
terence 55440 55439 0 15:21 pts/0 00:00:00 ./a.out
其中ssh进程号是97831,测试进程a.out是55439,fork的子进程号为55440
1.2命名管道(Named pipe)
//1.2命名管道通讯
terence@k8s-master:/mydata/linux$ mkfifo named_pipe_1
terence@k8s-master:/mydata/linux$ ll
drwxrwxr-x 2 terence terence 4096 Jan 8 16:35 ./
drwxrwxrwx 20 root root 4096 Jan 8 14:20 ../
prw-rw-r-- 1 terence terence 0 Jan 8 16:35 named_pipe_1|
1.2.1 named_pipe_write.c
#include
#include
#include
#include
int main(int argc, char const *argv[])
{
//O_RDWR 读写打开 不会阻塞
//O_RDONLY 只读 会阻塞
//O_WRONLY 只写 会阻塞
char buf[255]="";
int fd_write=open(argv[1],O_WRONLY);
printf("fd_write=%d\n",fd_write);
write(fd_write,"hello im writer",strlen("hello im writer"));
printf("写入 hello im writer\n");
return 0;
}
1.2.2 named_pipe_read.c
#include
#include
#include
#include
int main(int argc, char const *argv[])
{
//O_RDWR 读写打开 不会阻塞
//O_RDONLY 只读 会阻塞
//O_WRONLY 只写 会阻塞
char buf[255]="";
int fd_read=open(argv[1],O_RDONLY);
printf("fd_read=%d\n",fd_read);
read(fd_read,buf,sizeof(buf));
printf("read data:%s\n",buf);
return 0;
}
Res:
terence@k8s-master:/mydata/linux$ ./write named_pipe_1
---------------------------------------------------------------------------------------------------------------------------
阻塞...... terence@k8s-master:/mydata/linux$ terence@k8s-master:/mydata/linux$./read named_pipe_1
---------------------------------------------------------------------------------------------------------------------------
fd_write=3
写入 hello im writer
---------------------------------------------------------------------------------------------------------------------------
fd_read=3
read data:hello im writer
1.3 消息队列 (Message Queues)
1.3.1 msg_send.c
#include
#include
#include
#include
#include
#include
#include
//这个结构体可以自己定义,但必须要有一个消息类型type
typedef struct _msg
{
long mtype;
char mtext[50];
}MSG;
int main(int argc, char const *argv[])
{
key_t key;
int msgqid;
MSG msg;
key = ftok(".", 2021); // key 值
// 创建消息队列
msgqid = msgget(key, IPC_CREAT|0666);
if(msgqid == -1)
{
perror("msgget");
exit(-1);
}
msg.mtype = 100; //消息类型
strcpy(msg.mtext, "hello world!"); // 正文内容
/* 添加消息
msg_id:消息队列标识符
&msg:消息结构体地址
sizeof(msg)-sizeof(long):消息正文大小
0:习惯用0
*/
msgsnd(msgqid, &msg, sizeof(msg)-sizeof(long), 0);
printf("send: %s\n", msg.mtext);
return 0;
}
1.3.2 msg_read.c
#include
#include
#include
#include
#include
#include
#include
//这个结构体可以自己定义,但必须要有一个消息类型type
typedef struct _msg
{
long mtype;
char mtext[50];
}MSG;
int main(int argc, char const *argv[])
{
key_t key;
int msgqid;
MSG msg;
key = ftok(".", 2021); // key 值
// 创建消息队列
msgqid = msgget(key, IPC_CREAT|0666);
printf("msgqid=%d\n", msgqid);
if(msgqid == -1)
{
perror("msgget");
exit(-1);
}
memset(&msg, 0, sizeof(msg));
/* 取出类型为 10 的消息
msg_id:消息队列标识符
&msg:消息结构体地址
sizeof(msg)-sizeof(long):消息正文大小
(long)10:消息的类型
0:习惯用0
*/
msgrcv(msgqid, &msg, 10000, 100, 0);
printf("msg.mtext=%s\n", msg.mtext);
// 把消息队列删除
// IPC_RMID:删除标志位
//msgctl(msgqid, IPC_RMID, NULL);
return 0;
}
Res:
//msg_send
terence@k8s-master:/mydata/linux$ gcc -o msg_send msg_send.c
terence@k8s-master:/mydata/linux$ ./msg_send
send: hello world!
//查看队列
terence@k8s-master:/mydata/linux$ ipcs -q
------ Message Queues --------
key msqid owner perms used-bytes messages
0xe5013e9b 0 terence 666 56 1
//read
terence@k8s-master:/mydata/linux$ gcc -o msg_read msg_read.c
terence@k8s-master:/mydata/linux$ ./msg_read
msg.mtext=hello world!
1.3 信号 (Signal)
#include
#include
#include
#include
void SIGINT_handle(int sig_num)
{
//Ctrl + C 捕获
printf("reveice SIGINT signal %d \n", sig_num);
}
void SIGQUIT_handle(int sig_num)
{
//Ctrl + \ 捕获
printf("reveice SIGQUIT signal %d \n", sig_num);
}
int main(int argc, char argv[])
{
int i = 0;
signal(SIGINT, SIGINT_handle);
signal(SIGQUIT, SIGQUIT_handle);
while(i < 10){
printf("wait signal\n");
sleep(5);
i++;
}
return 0;
}
Res:
terence@k8s-master:/mydata/linux$ gcc -o signal signal.c
terence@k8s-master:/mydata/linux$ ./signal
wait signal
^Creveice SIGINT signal 2
wait signal
^\reveice SIGQUIT signal 3
---------------------------------------------------------------------------------------------------------------------------
//也可以在别的窗口命令行kill发送信号
terence@k8s-master:/mydata/linux$ ps -ef | grep signal
terence@k8s-master:/mydata/linux$ kill -SIGINT 72553
---------------------------------------------------------------------------------------------------------------------------
wait signal
Killed
1.4 信号量 (Semaphore)
1.4.1 sem.c 操作信号量
#include
#include
#include
#include
#include
#include
// struct sembuf{
// short sem_num; // 除非使用一组信号量,否则它为0
// short sem_op; // 信号量在一次操作中需要改变的数据,通常是两个数,一个是-1,即P(等待)操作,
// // 一个是+1,即V(发送信号)操作。
// short sem_flg; // 通常为SEM_UNDO,使操作系统跟踪信号,
// // 并在进程没有释放该信号量而终止时,操作系统释放信号量
// };
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
int main(int argc, char const *argv[])
{
key_t key;
int semid;
int num;
struct sembuf sem_b;
union semun sem_args;
unsigned short array[1]={1};
int op;
sem_args.array = array;
key = ftok(".", 2021); // key 值
printf("key=%d\n", (int)key);
printf("semid=%d\n", semid);
// 创建信号量
semid = semget(key, 1, IPC_CREAT|0666);
semctl(semid, 0, SETALL, sem_args);//0代表对1个信号来量初始化,即有1个资源
while(1){
num = rand() % 100 + 1;
if (num > 50)
{
op = 1;
}else{
op = -1;
}
sem_b.sem_num = 0;
sem_b.sem_op = op;//P()
sem_b.sem_flg = SEM_UNDO;
semop(semid, &sem_b, 1);
printf("set semval=%d\n", op);
sleep(3);
}
return 0;
}
1.4.2 sem_client.c 读取信号量
#include
#include
#include
#include
#include
int main(int argc, char const *argv[])
{
key_t key;
int semid;
int semval;
key = ftok(".", 2021); // key 值
printf("key=%d\n", (int)key);
printf("semid=%d\n", semid);
// 创建信号量
semid = semget(key, 1, IPC_CREAT|0666);
while(1){
semval = semctl(semid, 0, GETVAL, 0);
printf("semval=%d\n", (int)semval);
sleep(3);
}
return 0;
}
Res:
//set
terence@k8s-master:/mydata/linux$ gcc -o sem sem.c
terence@k8s-master:/mydata/linux$ ./sem
key=-452903269
semid=0
set semval=1
set semval=-1
set semval=1
set semval=-1
set semval=1
...
//查看
terence@k8s-master:~$ ipcs -s
------ Semaphore Arrays --------
key semid owner perms nsems
0xe5013e9b 0 terence 666 1
terence@k8s-master:~$
//get
terence@k8s-master:/mydata/linux$ gcc -o sem_client sem_client.c
terence@k8s-master:/mydata/linux$ ./sem_client
key=-452903269
semid=0
semval=1
semval=2
semval=3
semval=4
...
1.5 共享内存 (Shared Memory)
1.5.1 mem_write.c 写入共享内存
#include
#include
#include
#include
int main(int argc, char const *argv[])
{
int shmid;
key_t key;
//创建共享内存的key
key = ftok(".", 2021); // key 值
if (key == -1)
{
perror("ftok error");
}
// 创建1024字节的共享内存
shmid = shmget(key, 1024, IPC_CREAT|0666);
printf("shmid=%d\n", shmid);
// 共享内存连接到本进程某个指针
char *shmadd;
shmadd = shmat(shmid, NULL, 0);
char *msg;
msg = "Hello World!";
printf("set data to shared-memory :%s\n", msg);
// Set data
strcpy(shmadd, msg);
// 分离
shmdt(shmadd);
return 0;
}
1.5.2 mem_read.c 读取共享内存
#include
#include
#include
#include
#include
int main(int argc, char const *argv[])
{
int shmid;
key_t key;
//创建共享内存的key
key = ftok(".", 2021); // key 值
if (key == -1)
{
perror("ftok error");
}
// 创建|打开1024字节的共享内存
shmid = shmget(key, 1024, IPC_CREAT|0666);
printf("shmid=%d\n", shmid);
// 共享内存连接到本进程某个指针
char *shmadd;
shmadd = shmat(shmid, NULL, 0);
printf("read data from shared-memory :%s\n", shmadd);
// 分离
shmdt(shmadd);
// 删除共享内存
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
1.6 Socket
这里使用TCP示例
1.6.1 socket_server.c 服务端
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MYPORT 8887
#define QUEUE 20
#define BUFFER_SIZE 1024
int main(int argc, char const *argv[])
{
//定义sockfd
int server_socket = socket(AF_INET,SOCK_STREAM, 0);
//定义sockaddr_in
struct sockaddr_in server_sockaddr;
memset(&server_sockaddr, 0, sizeof(server_sockaddr)); //每个字节都用0填充
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(MYPORT);
server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
//bind,成功返回0,出错返回-1
if(bind(server_socket,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1)
{
perror("bind");
exit(1);
}
printf("blind...\n");
//listen,成功返回0,出错返回-1
if(listen(server_socket,QUEUE) == -1)
{
perror("listen");
exit(1);
}
printf("listen...\n");
//客户端套接字
char buffer[BUFFER_SIZE];
struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);
int conn;
//成功返回非负描述字,出错返回-1
conn = accept(server_socket, (struct sockaddr*)&client_addr, &length);
if (conn == -1)
{
printf("accept error....\n");
close(server_socket);
exit(1);
}
printf("read socket=%d\n",conn);
memset(buffer,0,sizeof(buffer));
int len = read(conn, buffer, sizeof(buffer));
printf("read data from %d:%s \n", conn, buffer);
memset(buffer,0,sizeof(buffer));
strcpy(buffer, "我收到啦!");
write(conn, buffer, sizeof(buffer));
printf("send data to %d:%s \n", conn,buffer);
printf("close....\n");
close(conn);
close(server_socket);
return 0;
}
1.6.2 socket_client.c 服务端
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MYPORT 8887
#define BUFFER_SIZE 1024
int main()
{
///定义sockfd
int sock_cli = socket(AF_INET,SOCK_STREAM, 0);
///定义sockaddr_in
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(MYPORT); ///服务器端口
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服务器ip
///连接服务器,成功返回0,错误返回-1
if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
perror("connect");
exit(1);
}
printf("connected!\n");
char sendbuf[BUFFER_SIZE];
char recvbuf[BUFFER_SIZE];
memset(sendbuf , 0, sizeof(sendbuf));
strcpy(sendbuf, "你好啊,我是client!");
write(sock_cli, sendbuf, strlen(sendbuf)); ///发送
printf("send data %s \n", sendbuf);
memset(recvbuf , 0, sizeof(recvbuf));
read(sock_cli, recvbuf, sizeof(recvbuf)); ///接收
printf("get data %s \n", recvbuf);
printf("close....\n");
close(sock_cli);
return 0;
}
Res:
//server
terence@k8s-master:/mydata/linux$ gcc -o socket_server socket_server.c
terence@k8s-master:/mydata/linux$ ./socket_server
blind...
listen...
read socket=4
read data from 4:你好啊,我是client!
send data to 4:我收到啦!
close....
//client
terence@k8s-master:/mydata/linux$ gcc -o socket_client socket_client.c
terence@k8s-master:/mydata/linux$ ./socket_client
connected!
send data 你好啊,我是client!
get data 我收到啦!
close....~~~~