Rumah  >  Artikel  >  Operasi dan penyelenggaraan  >  Bagaimana untuk melaksanakan komunikasi antara proses Linux

Bagaimana untuk melaksanakan komunikasi antara proses Linux

王林
王林ke hadapan
2023-05-21 16:28:521603semak imbas

    Memori dikongsi

    • Memori bersama boleh dikatakan sebagai kaedah komunikasi antara proses yang paling berguna dan bentuk IPC terpantas . Apakah proses yang berbeza A dan B berkongsi memori bermakna: sekeping memori fizikal yang sama dipetakan ke ruang alamat proses masing-masing bagi proses A dan B. Proses A boleh melihat kemas kini kepada data dalam memori yang dikongsi oleh proses B pada masa yang sama. , dan sebaliknya.

    • Memandangkan berbilang proses berkongsi kawasan memori yang sama, beberapa jenis mekanisme penyegerakan, kunci mutex dan semaphore diperlukan.

    Faedah: Kecekapan tinggi, proses boleh terus membaca dan menulis memori tanpa menyalin sebarang data, manakala kaedah komunikasi seperti paip dan baris gilir mesej memerlukan empat kali dalam kernel dan ruang pengguna Replikasi data .

    Dan hanya apabila menyahpeta, kandungan memori yang dikongsi akan ditulis untuk memperingatinya

    Memori dikongsi membenarkan proses yang berbeza untuk memperuntukkan pemetaan ruang pada ruang alamat maya mereka sendiri melalui objek kernel Kepada ruang ingatan fizikal yang sama, ruang ingatan fizikal ini boleh diakses oleh setiap proses yang dipetakan kepadanya. (Sumber kritikal)

    Bagaimana untuk melaksanakan komunikasi antara proses Linux

    Memori dikongsi membenarkan dua proses yang tidak berkaitan mengakses memori logik yang sama .

    Memori dikongsi ialah cara yang sangat cekap untuk berkongsi dan memindahkan data antara dua proses yang sedang berjalan.

    Memori yang dikongsi antara proses yang berbeza biasanya disusun sebagai segmen memori fizikal yang sama.

    Proses boleh menyambungkan segmen memori kongsi yang sama ke dalam ruang alamat mereka sendiri, dan semua proses boleh mengakses alamat dalam memori kongsi seolah-olah ia diperuntukkan oleh fungsi bahasa C malloc().

    Dan jika proses menulis data ke memori kongsi, perubahan akan menjejaskan serta-merta sebarang proses lain yang boleh mengakses memori kongsi yang sama.

    mmap() dan panggilan sistem yang berkaitan

    mmap ialah fungsi pemetaan memori yang disediakan oleh sistem pengendalian Linux kepada ruang pengguna Ramai orang hanya tahu bahawa perkongsian memori antara proses boleh diselesaikan melalui mmap dan mengurangkan bilangan salinan data daripada mod pengguna kepada mod kernel, tetapi saya tidak mempunyai pemahaman yang mendalam tentang cara mmap dilaksanakan dalam sistem pengendalian dan apakah prinsipnya

    Bagaimana untuk melaksanakan komunikasi antara proses Linux

    Gunakan sistem mmap() Dipanggil, proses boleh berkongsi memori dengan memetakan fail biasa yang sama. Selepas fail biasa dipetakan ke ruang alamat proses, proses boleh mengakses fail seperti memori biasa tanpa memanggil operasi baca dan tulis.

    Nota: mmap tidak direka sepenuhnya untuk IPC Ia hanya satu kaedah aplikasi IPC ia sendiri menyediakan akses kepada fail biasa seperti mengakses memori biasa.

    Dicapai dengan menggunakan segmen memori maya dengan set kebenaran khas. Apabila membaca atau menulis segmen memori maya jenis ini, sistem pengendalian akan membaca dan menulis bahagian fail cakera yang sepadan.

    Fungsi mmap mencipta penunjuk ke kawasan memori yang dikaitkan dengan kandungan fail yang boleh diakses melalui deskriptor fail terbuka

    Diterangkan di bawah :

    mmap()

    #include <sys/mman.h>
    
    void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

    Anda boleh menukar nilai offset permulaan data dalam fail yang diakses melalui segmen memori kongsi dengan menghantar parameter offset.

    Penerangan fail terbuka diberikan oleh parameter fd.

    Jumlah data yang boleh diakses (iaitu panjang segmen memori) ditetapkan oleh parameter panjang.

    Anda boleh meminta penggunaan alamat memori tertentu melalui parameter addr. Jika nilainya adalah sifar, penunjuk hasil akan diperuntukkan secara automatik. Kegagalan untuk mengikuti amalan ini mengurangkan kemudahalihan program anda kerana julat alamat yang tersedia berbeza pada sistem yang berbeza.

    Parameter prot digunakan untuk menetapkan kebenaran akses segmen memori. Ia adalah hasil bitwise ATAU nilai malar berikut

    • PROT_READ Segmen memori boleh dibaca.

    • PROT_WRITE Segmen memori boleh ditulis.

    • Segmen memori PROT_EXEC boleh dilaksanakan.

    • PROT_NONE segmen memori tidak boleh diakses.

    parameter flag mengawal kesan perubahan pada segmen memori oleh atur cara:

    Bagaimana untuk melaksanakan komunikasi antara proses Linux

    mmap() digunakan untuk memori dikongsi Dua kaedah mengukur dan menjumlahkan adalah seperti berikut:

    Gunakan pemetaan memori yang disediakan oleh fail biasa, yang sesuai untuk sebarang proses Untuk menggunakan kaedah ini, anda perlu membuka atau mencipta fail terlebih dahulu, dan kemudian panggil ngmmap. Kod panggilan biasa adalah seperti berikut:

    fd = open(name.falg.mode);
    if(fd < 0)
    ptr = mmap(NULL,len.PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);

    使用特殊文件提供的内存映射,适用于具有亲缘关系的进程之间,由于父子进程特殊的亲缘关系,在父进程中先调用mmap,调用fork,那么在代用fork之后,子进程可以继承父进程匿名映射后的地址空间,同样也继承mmap返回的地址,这样父子进程就可以通过映射区域进行通信了。(注意:一般来说,子进程单独维护从父进程继承而来的一些变量,而mmap()返回的地址由父子进程共同维护)【具体使用实现敬请期待博主整理】

    munmap()

    用于解除内存映射,取消参数start所指的映射内存的起始地址,参数length则是欲取消的内存大小,当进程结束或者利用exec相关函数来执行其他程序时,映射内存会自动解除,但关闭对应的文件描述符时不会解除映射。

    #include <sys/mman.h>
    
    int munmap(void *addr, size_t length);

    共享内存的使用

    与信号量一样,在Linux中也提供了一组函数接口用于使用共享内存,而且使用共享共存的接口还与信号量的非常相似,而且比使用信号量的接口来得简单。它们声明在头文件 sys/shm.h 中。 

    1.获取或创建内核对象,并且制定共享内存的大小(系统分配物理空间是,按照页进行分配)

    int shmget(key_t key, int size, int flag);

    只是创建内核对象,并申请物理空间

    • key_t key:与信号量的semget函数一样,程序需要提供一个参数key(非0整数),它有效地为共享内存段命名,不同的进程通过相同的key值来访问同一块共享内存

    • int size:size以字节为单位指定需要共享的内存容量

    • int flag:falg是权限标志,它的作用与open函数的mode参数一样,如果要想在key标识的共享内存不存在时,创建它的话,可以与IPC_CREAT做或操作。共享内存的权限标志与文件的读写权限一样,举例来说,0644,它表示允许一个进程创建的共享内存被内存创建者所拥有的进程向共享内存读取和写入数据,同时其他用户创建的进程只能读取共享内存。

    返回值

    • 调用成功后,shmget()函数会返回一个非负整数,用作后续共享内存函数的共享内存标识符,该标识符与key相关。

    • 调用失败返回-1.

    2.分配自己虚拟地址空间映射到共享内存的物理空间上

    void *shmat(int shmid,const void *addr, int flag);
    • shmid:shmid是由shmget()函数返回的共享内存标识。

    • void *addr:addr指定共享内存连接到当前进程中的地址位置,通常为NULL,表示让系统来选择共享内存的地址。

    • int flag:flag是一组标志位,通常为0。

    调用成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1.

    3.断开当前进程与共享内存的映射

    不使用删除而使用断开的原因是因为:也许还存在其他的进程会继续使用这块共享内存

    int shmdt(const void *addr);

    4.操作共享内存的方法

    int shmctl(int shmid, int cmd, struct shmid_t *buf);
    • int shmid:shmid是shmget()函数返回的共享内存标识符。

    • int cmd:command是要采取的操作,它可以取下面的三个值 :

    IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。

    IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值

    IPC_RMID:删除共享内存段

    • struct shmid_t *buf:buf是一个结构指针,它指向共享内存模式和访问权限的结构

    因为有连接计数器,除非最后一个进程与该共享段断开连接,则删除该共享段。否则,并不会真正删除该共享段,但是共享内存的内核对象会被立即删除,不能使用shmat方法与该段连接。 

    一个进程调用该方法删除后,不会影响之前已经和该共享存储段连接的进程

    下面我们利用共享内存来进行一个简单的测试:

    Bagaimana untuk melaksanakan komunikasi antara proses Linux

    Bagaimana untuk melaksanakan komunikasi antara proses Linux

    完成下面的过程,

    Bagaimana untuk melaksanakan komunikasi antara proses Linux

    成功在共享内存中读到了数据

    Bagaimana untuk melaksanakan komunikasi antara proses Linux

    #include<stdio.h>
    #include<stdlib.h>
    #include<assert.h>
    #include<string.h>
    #include<unistd.h>
    
    #include<sys/types.h>
    #include<sys/ipc.h>
    #include<sys/shm.h>
    
    #include"sem.h"
    
    #define READSEM 1
    #define WRITESEM 0
    
    int main()
    {
    	int shmid = shmget((key_t)1234,128,0664 | IPC_CREAT);
    	assert(shmid != -1);
    
    	char *ptr = (char*)shmat(shmid,NULL,0);
    	assert(ptr != (char*)-1);
    	
    	int initVal[] = {1,0};
    	int semid = SemGet(1234,intVal,2);
    	assert(semid != -1);
    	
    	//A进程写
    	while(1)
    	{
    		SemP(semid,WRITESEM);
    		printf("Input:");
    		
    		fgets(ptr,127,stdin);
    		
    		SemV(semid,READSEM);
    		
    		if(strncmp(ptr,"end",3) == 0)
    		{
    			break;
    		}
    	}
    	
    	shmdt(ptr);
    	exit(0);
    }
    #include<stdio.h>
    #include<stdlib.h>
    #include<assert.h>
    #include<string.h>
    #include<unistd.h>
    
    #include<sys/types.h>
    #include<sys/ipc.h>
    #include<sys/shm.h>
    
    #include"sem.h"
    
    #define READSEM 1
    #define WRITESEM 0
    
    int main()
    {
    	int shmid = shmget((key_t)1234,128,0664 | IPC_CREAT);
    	assert(shmid != -1);
    
    	char *ptr = (char*)shmat(shmid,NULL,0);
    	assert(ptr != (char*)-1);
    	
    	int initVal[] = {1,0};
    	int semid = SemGet(1234,intVal,2);
    	assert(semid != -1);
    	
    	//B进程读
    	while(1)
    	{
    		SemP(semid,READSEM);
    		
    		if(strncmp(ptr,"end",3) == 0)
    		{
    			break;
    		}
    		
    		int i = 0;
    		for(;i < strlen(ptr) - 1;i++)
    		{
    			printf("%c",toupper(ptr[i]));
    			fflush(stdout);
    			sleep(1);
    		}
    		printf("\n");
    		SemV(semid,WRITESEM);
    	}
    	
    	shmdt(ptr);
    	exit(0);
    }

    从上面的代码中我们可以看出: 

    共享内存是最快的IPC,在通信过程中少了两次数据的拷贝。(相较于管道)

    命令管理共享内存

    • 查看 ipcs -m

    • 删除 ipcrm -m shmid

    Atas ialah kandungan terperinci Bagaimana untuk melaksanakan komunikasi antara proses Linux. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

    Kenyataan:
    Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam