ipc-test.bk and mmap is also similar.

1.config tab-4

vi /etc/virc或者

1.配置文件中如果要添加注释,不能用#,要使用”

2.u命令回退上次的操作

3.复制不带行号,在/etc/virc的末尾添加se mouse+=a

" add tab space

set ts=4 "只设置这个就能把tab缩进为4,加上下面的tab直接被替换成4个空格,不是tab了,make出错

"set softtabstop=4
"set shiftwidth=4
"set expandtab
"set autoindent

" 显示行号,但是也会复制到行号,直接注释
"set nu

2.tree and makefile 

1.tree ipc/
ipc/
├── clean.sh
├── client
│   ├── client.c
│   └── client.h
├── include
│   └── global_api.h
├── ipc
├── main
│   └── main.c
├── makefile
└── server
    ├── server.c
    └── server.h

4 directories, 9 files


2.cat makefile 
#gcc ./main/main.c ./server/server.c ./client/client.c -o ipc 
#只写这一行应该写在shell里而不是makefile
all: ipc

ipc: main/main.c server/server.c client/client.c  #加不加./都一样
    gcc -o ipc main/main.c server/server.c client/client.c # -o 在哪里都一样

clean:
    rm -rf ipc


3.cat clean.sh
make clean

3.注意事项:shm族函数并没有信号的通知机制,需要我们继续使用sem族函数 

 增加通知机制

server.c

cat server/server.c 
#include "../include/global_api.h"


void server_init(){
	/*key_t key = ftok(".", 1); //使用绝对路径比较合适
	if(key < 0){
		printf("\nftok err.\n");
	}*/
	int shmid = shmget(IPC_KEY, sizeof(int), IPC_CREAT | 0664);//0666);
    if (shmid == -1) {  
        perror("shmget failed");  
        exit(1);  
    }
	char* shared_mem = (char*)shmat(shmid, NULL, 0);
	if(shared_mem == (void*)-1){
		perror("shmat failed");
	}

	struct sembuf op; 
	int semid = semget(IPC_KEY, 1, IPC_CREAT | 0664);
	
	/*union semun arg;  //gcc 可能不支持,先注释掉
    arg.val = 0;  
    if (semctl(semid, 0, SETVAL, arg) == -1) {  
        perror("semctl SETVAL");  
        exit(1);  
    }*/ 
 
	while(1){
		sleep(1);

    	op.sem_num = 0;  // 信号量在信号量集中的索引
    	op.sem_op = -1;   //阻塞等待通知的到来
    	op.sem_flg = 0;  // 表示这是一次常规的操作
    	if (semop(semid, &op, 1) == -1) {
        	perror("semop");
        	exit(1);
    	}
		printf("i got it, shard_mem:[%s]\n", shared_mem);//[%c]\n", shared_mem);

	}	
}

client.c

cat client/client.c
#include "../include/global_api.h"


void client_init(){
	int shmid = shmget(IPC_KEY, sizeof(int), IPC_CREAT);// | 0666);	
    if (shmid == -1) {  
        perror("shmget failed");  
        exit(1);  
    }
	char* shared_mem = (char*)shmat(shmid, NULL, 0);
	if(shared_mem == (void*)-1){
		perror("shmat failed");
	}

    struct sembuf op;  
  
    // 获取信号量集  
    int semid = semget(IPC_KEY, 1, 0);  
    if (semid == -1) {  
        perror("semget");  
        exit(1);  
    }  
  	
	*shared_mem = 'a' - 1;  	

	while(1){
		sleep(1);
		*shared_mem += 1;
    	op.sem_num = 0;  // 信号量在信号量集中的索引
   		op.sem_op = 1;  // 通知
    	op.sem_flg = 0;  //表示这是一次常规的操作
    	if (semop(semid, &op, 1) == -1) {
        	perror("semop");
        	exit(1);
    	}
		printf("\nclient modify the char.\n");
		
	}
}

 

 4.how to make the shared_mem to complete IPC(没有增加通知,只需要把上面3的code替换下来即可)

main.c

cat main/main.c 
#include "../include/global_api.h"

int main(){
    pid_t server_pid = fork();
    if(server_pid < 0){
        printf("\nfork err\n");
    }else if(server_pid == 0){
        printf("\nfork server success.\n");
		server_init();
    }

	pid_t client_pid = fork();
    if(client_pid < 0){
        printf("\nfork err\n");
    }else if(client_pid == 0){
        printf("\nfork client success.\n");
		client_init();
    }else{
		int state;
		waitpid(server_pid, &state, 0);
		waitpid(client_pid, &state, 0);
	}

	return 0;
}

waitpid(server_pid, &state, 0); && waitpid(client_pid, &state, 0);是必须的,不然main进程直接返回了

server.c:server不用ftok生成唯一的key,直接在global_api.h里大家使用相同的IPC_KEY即可,shmget的第二个参数是共享内存的大小:

或者用一个更好的方法生成KEY:

    // 使用ftok生成一个唯一的键  
    key = ftok("/tmp", 'R');  
    if (key == (key_t)-1) {  
        perror("ftok");  
        exit(1);  
    }  
cat server/server.c 
#include "../include/global_api.h"


void server_init(){
	/*key_t key = ftok(".", 1);
	if(key < 0){
		printf("\nftok err.\n");
	}*/
	int shmid = shmget(IPC_KEY, sizeof(int), IPC_CREAT | 0664);//0666)i;
    if (shmid == -1) {  
        perror("shmget failed");  
        exit(1);  
    }
	char* shared_mem = (char*)shmat(shmid, NULL, 0);
	if(shared_mem == (void*)-1){
		perror("shmat failed");
	}

	while(1){
		sleep(1);
		printf("shard_mem:[%s]\n", shared_mem);//[%c]\n", shared_mem);

	}	
}

server.h

cat server/server.h
void server_init();

client.c:client不用0664,因为server已经创建了共享空间的空间号,我们只需要加入即可

cat client/client.c
#include "../include/global_api.h"


void client_init(){
	int shmid = shmget(IPC_KEY, sizeof(int), IPC_CREAT);// | 0666);	
    if (shmid == -1) {  
        perror("shmget failed");  
        exit(1);  
    }
	char* shared_mem = (char*)shmat(shmid, NULL, 0);
	if(shared_mem == (void*)-1){
		perror("shmat failed");
	}	
	shared_mem[0] = 'a'; //or *shared_mem = 'a';
	while(1){
		sleep(1);
		*shared_mem += 1;
		printf("\nclient modify the char\n");
		
	}
}

client.h

cat client/client.h
void client_init();

golbal_api.h

cat include/global_api.h 
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <unistd.h>
#include <sys/wait.h>

#include "../client/client.h"
#include "../server/server.h"


#define IPC_KEY 1234

5.other code

dd if=/dev/zero of=/tmp/shared_memory bs=1M count=1

这条命令在Linux或Unix系统中用于通过dd(data duplicator)工具创建一个特定大小的文件。具体来说:

if=/dev/zero:指定输入文件为/dev/zero,这是一个特殊的设备文件,它提供无限的零字节(\0)。
of=/tmp/shared_memory:指定输出文件为/tmp/shared_memory。这意味着从输入文件(/dev/zero)读取的数据将被写入到这个文件中。
bs=1M:设置块大小为1兆字节(1MB)。这意味着每次从输入文件读取和写入输出文件的数据块大小是1MB。
count=1:指定从输入文件读取并写入输出文件的数据块数量为1。
综合起来,这条命令将创建一个大小为1MB的文件/tmp/shared_memory,文件内容全部为零字节。这样的文件常用于需要预定大小空白文件的场合,例如作为共享内存区域的占位符。

进程A:
#include <stdio.h>  
#include <stdlib.h>  
#include <fcntl.h>  
#include <sys/mman.h>  
#include <unistd.h>  
  
int main() {  
    int *flag_ptr;  
    int fd = open("/tmp/shared_memory", O_RDWR | O_CREAT, 0666);  
    if (fd == -1) {  
        perror("open");  
        exit(1);  
    }  
  
    // 将文件大小设置为足够大的值以容纳我们的int  
    if (ftruncate(fd, sizeof(int)) == -1) {  
        perror("ftruncate");  
        exit(1);  
    }  
  
    // 映射文件到内存中  
    flag_ptr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  
    if (flag_ptr == MAP_FAILED) {  
        perror("mmap");  
        exit(1);  
    }  
  
    // 写入flag  
    *flag_ptr = 1;  
  
    // 等待其他进程或进行其他操作...  
  
    // 清理  
    munmap(flag_ptr, sizeof(int));  
    close(fd);  
  
    return 0;  
}

进程B:
#include <stdio.h>  
#include <stdlib.h>  
#include <fcntl.h>  
#include <sys/mman.h>  
#include <unistd.h>  
  
int main() {  
    int *flag_ptr;  
    int fd = open("/tmp/shared_memory", O_RDWR);  
    if (fd == -1) {  
        perror("open");  
        exit(1);  
    }  
  
    // 映射文件到内存中  
    flag_ptr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  
    if (flag_ptr == MAP_FAILED) {  
        perror("mmap");  
        exit(1);  
    }  
  
    // 读取flag  
    int flag = *flag_ptr;  
    printf("Read flag: %d\n", flag);  
  
    // ... 进行其他操作 ...  
  
    // 清理  
    munmap(flag_ptr, sizeof(int));  
    close(fd);  
  
    return 0;  
}

匿名mmap:其实就是加了标志位,即MAP_SHAREDMAP_ANONYMOUS(或MAP_ANON),并且把使用的fd直接变成-1

#include <sys/mman.h>  
#include <unistd.h>  
#include <stdio.h>  
  
int main() {  
    // 映射区域的大小,例如4个字节  
    size_t size = 4;  
      
    // 创建匿名映射区域  
    int *shared_memory = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);  
      
    if (shared_memory == MAP_FAILED) {  
        perror("mmap failed");  
        return 1;  
    }  
      
    // ... 后续代码 ...  
}

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值