色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何實現一套linux進程間通信的機制

科技綠洲 ? 來源:Linux開發架構之路 ? 作者:Linux開發架構之路 ? 2023-11-10 14:56 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

我們知道linux的進程的間通信的組件有管道,消息隊列,socket, 信號量,共享內存等。但是我們如果自己實現一套進程間通信的機制的話,要怎么做?了解android 開發的可能會知道,android里面有個binder機制,簡單來說,就是一個進程往binder里面寫數據,另一個進程從binder里面讀出數據。

圖片

所以我們也可以按照binder的思路來設計一個自己的進程間通信組件。

原理

圖片

我們的設計思路很簡單,我們首先需要注冊一個字符設備文件叫**/dev/channel**, 同時需要為這個設備編寫驅動,此時某個進程A向設備文件寫數據,同時如果該設備可讀,我們就通知另一個進程B去讀該進程。 我們怎么知道該設備是否可讀可寫呢?使用poll來管理,因為該設備驅動屬于一個IO, 打開一個設備就有fd, 有了fd我們就可以使用poll來管理。

代碼實現

首先驅動程序:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include


#ifndef CHANNEL_MAJOR
#define CHANNEL_MAJOR 96
#endif

#ifndef CHANNEL_NR_DEVS
#define CHANNEL_NR_DEVS 2
#endif

#ifndef CHANNEL_SIZE
#define CHANNEL_SIZE 4096
#endif

#define ENABLE_POLL 1

struct channel {
char *data;
unsigned long size;
#if ENABLE_POLL
wait_queue_head_t inq;
#endif
};

static int channel_major = CHANNEL_MAJOR;
module_param(channel_major, int, S_IRUGO);

struct channel *channel_devp;
struct cdev cdev;

char have_data = 0;

int channel_open (struct inode *inode, struct file *filp) {
struct channel *channel;

int num = MINOR(inode->i_rdev); //設備讀了多少次
if (num >= CHANNEL_NR_DEVS)
return -ENODEV;

channel = &channel_devp[num];
filp->private_data = channel;

return 0;
}

int channel_release (struct inode *inode, struct file *filp) {
return 0;
}

#if ENABLE_POLL
unsigned int channel_poll (struct file *filp, struct poll_table_struct *wait) {
struct channel *channel = filp->private_data;
unsigned int mask = 0;

poll_wait(filp, &channel->inq, wait); // poll 阻塞

if (have_data)
mask |= (POLLIN | POLLRDNORM);

return mask;
}
#endif


int channel_mmap (struct file *filp, struct vm_area_struct *vma) {
struct channel *channel = filp->private_data;

vma->vm_flags |= VM_IO;
vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP);

if (remap_pfn_range(vma, vma->vm_start, virt_to_phys(channel->data) >> PAGE_SHIFT,
vma->vm_end-vma->vm_start, vma->vm_page_prot)) {
return -EAGAIN;
}

return 0;
}

ssize_t channel_read (struct file *filp, char __user * buffer, size_t size, loff_t *ppos) {
unsigned long p = *ppos;
unsigned int count = size;

int ret = 0;
struct channel *channel = filp->private_data; // 讀私有空間

if (p >= CHANNEL_SIZE) return 0;
if (count > CHANNEL_SIZE- p)
count = CHANNEL_SIZE- p;

#if ENABLE_POLL
while (!have_data) {
if (filp->f_flags & O_NONBLOCK) return -EAGAIN;

wait_event_interruptible(channel->inq, have_data);
}
#endif
if (copy_to_user(buffer, (void*)(channel->data + p), count)) { //拷貝到用戶空間
ret = -EFAULT;
} else {
ret = strlen(buffer);
channel->size -= ret;
printk(KERN_INFO "read %d byte(s) from %ldn", ret, p);
}

have_data = 0;
return ret;
}

ssize_t channel_write (struct file *filp , const char __user * buffer, size_t size, loff_t *ppos) {
int ret = 0;
unsigned long p = *ppos;
unsigned int count = size;

struct channel *channel = filp->private_data; // 寫道文件的私有空間
if (p >= CHANNEL_SIZE) return 0;
if (count > CHANNEL_SIZE- p)
count = CHANNEL_SIZE- p;

if (copy_from_user(channel->data +p, buffer, count)) { // 從user -> kernel
return -EFAULT;
} else {
*ppos += count;
ret = count;
channel->size += count;
*(channel->data+p + count) = '?';

printk(KERN_INFO "written %d byte(s) from %ldn", count, p);
}

#if ENABLE_POLL
have_data = 1;
wake_up(&channel->inq);
#endif

return ret;
}

loff_t channel_llseek (struct file *filp, loff_t offset, int whence) { //偏移
loff_t newpos;

switch (whence)
{
case 0:
newpos = offset;
break;
case 1:
newpos = filp->f_pos + offset;
break;
case 2:
newpos = CHANNEL_SIZE - 1 + offset;
break;
default:
return -EINVAL;
}

if (newpos < 0 || newpos > CHANNEL_SIZE) return -EINVAL;

filp->f_pos = newpos;

return newpos;
}

static const struct file_operations channel_fops =
{
.owner = THIS_MODULE,
.llseek = channel_llseek,
.read = channel_read,
.write = channel_write,
.open = channel_open,
.release = channel_release,
.poll = channel_poll,
.mmap = channel_mmap,
};


static int channel_init(void) {
int reslut;
int i;

dev_t devno = MKDEV(channel_major, 0); // 創建一個主設備號為96,次設備號為0的設備
if (channel_major) {
reslut = register_chrdev_region(devno, CHANNEL_NR_DEVS, "channel"); // 注冊設備
} else {
reslut = alloc_chrdev_region(&devno, 0, CHANNEL_NR_DEVS, "channel");
}

if (reslut < 0) return reslut;

cdev_init(&cdev, &channel_fops); //初始化字符設備
cdev.owner = THIS_MODULE;

cdev_add(&cdev, MKDEV(channel_major, 0), CHANNEL_NR_DEVS); //添加到字符設備中

channel_devp = kmalloc(CHANNEL_NR_DEVS *sizeof(struct channel), GFP_KERNEL); //為 我們的buffer 分配一塊空間
if (!channel_devp) {
reslut = -ENOMEM;
goto fail_malloc;
}
memset(channel_devp, 0, sizeof(struct channel));

for (i = 0; i < CHANNEL_NR_DEVS; i++) {
channel_devp[i].size = CHANNEL_SIZE;
channel_devp[i].data = kmalloc(CHANNEL_SIZE, GFP_KERNEL);
memset(channel_devp[i].data, 0, CHANNEL_SIZE);
#if ENABLE_POLL
init_waitqueue_head(&(channel_devp[i].inq));
#endif
}
printk(KERN_INFO "ntychannel_init");

return 0;
fail_malloc:
unregister_chrdev_region(devno, 1);
return reslut;
}

static void channel_exit(void) {
printk(KERN_INFO "channel_exit");
cdev_del(&cdev);
kfree(channel_devp);

unregister_chrdev_region(MKDEV(channel_major, 0), 2);
}


MODULE_AUTHOR("birate");
MODULE_LICENSE("GPL");

module_init(channel_init); // 設備初始化
module_exit(channel_exit); //設備退出

編寫Makefile文件:

obj-m += channel.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
  1. 使用 make 命令。編譯出我們需要的channel.ko文件。
  2. 使用 insmod channel.ko, 向kernel中插入 我們的module
  3. 使用mknod /dev/channel c 96 0, 創建一個/dev/channel 的字符設備,主設備號為96,次設備號為0;

編寫我們的應用程序:

channel_app.c

#include
#include
#include

#include
#include
#include
#include
#include

#include

#define BUFFER_LENGTH 128

int main () {
int fd = open("/dev/channel", O_RDWR);
if (fd < 0) {
printf("open failed: errno : %sn", strerror(errno));
return -1;
}

char *buffer = (char *)malloc(BUFFER_LENGTH);
memset(buffer, 0, BUFFER_LENGTH);

char *start = mmap(NULL, BUFFER_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

fd_set rds;
FD_ZERO(&rds);
FD_SET(fd, &rds);

while(1) {
int ret = select(fd+1, &rds, NULL, NULL, NULL);
if (ret < 0) {
printf("select errorn");
exit(1);
}
if (FD_ISSET(fd, &rds)) {
#if 0
strcpy(buffer, start);
printf("channel: %sn", buffer);
#else
read(fd, buffer, BUFFER_LENGTH);
printf("channel: %sn", buffer);
#endif
}
}

munmap(start, BUFFER_LENGTH);
free(buffer);
close(fd);

return 0;
}

應用程序很簡單,我們使用 gcc -o channel_app channel_app.c , 編譯出可執行文件,在一個進程中執行channel_app, 另一個進程使用echo " " > /dev/channel 去向設備文件中寫就可以了。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 數據
    +關注

    關注

    8

    文章

    7259

    瀏覽量

    92068
  • 通信
    +關注

    關注

    18

    文章

    6209

    瀏覽量

    137906
  • Linux
    +關注

    關注

    87

    文章

    11519

    瀏覽量

    214012
  • 字符
    +關注

    關注

    0

    文章

    237

    瀏覽量

    25619
  • 組件
    +關注

    關注

    1

    文章

    533

    瀏覽量

    18449
收藏 0人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    Linux進程如何實現共享內存通信

    這次我們來講Linux進程通信中重要的通信方式:共享內存作為Linux軟件開發攻城獅,
    發表于 04-26 17:14 ?825次閱讀

    linux操作系統下的進程通信設計

    )的進程通信機制Linux則把兩者繼承了下來,如圖示:其中,最初Unix IPC包括:管道、FIFO、信號;System V IPC包括
    發表于 04-16 09:17

    Linux進程通信方式-管道

    Linux進程通信方式-管道分享到: 本文關鍵字: linux 管道通信
    發表于 08-29 15:29

    Linux進程通信

    華清遠見嵌入式linux學習資料《Linux進程通信》,通過前面的學習,讀者已經知道了進程
    發表于 09-04 10:07

    Linux學習雜談】之進程通信

    本帖最后由 michael_llh 于 2016-10-17 13:14 編輯 我們在Linux應用編程當中如果需要用到多個進程來完成個任務的話那么我們就沒有辦法避開進程
    發表于 10-15 14:45

    Linux進程通信——使用共享內存

    Linux進程通信——使用共享內存 圖文詳情見附件
    發表于 11-21 10:53

    Linux現有的所有進程IPC方式

    在開始回答前,先簡單概括性地說說Linux現有的所有進程IPC方式:1. **管道:**在創建時分配個page大小的內存,緩存區大小比較有限;2. 消息隊列:信息復制兩次,額外的C
    發表于 08-20 06:17

    哪些方式可以實現Linux系統下的進程通信

    哪些方式可以實現Linux系統下的進程通信進程與線程有哪些不同之處呢?
    發表于 12-24 06:38

    進程通信Linux進程通信概述

    人們現在廣泛使用的手機等方式。本章就是講述如何建立這些不同的通話方式,就像人們有多種通信方式樣。 Linux下的進程通信手段基本上是從UN
    發表于 10-18 16:21 ?0次下載

    進程與線程通信方式

    進程通信則不同,它的數據空間的獨立性決定了它的通信相對比較復雜,需要通過操作系統。以前進程
    的頭像 發表于 04-09 15:58 ?9179次閱讀
    <b class='flag-5'>進程</b><b class='flag-5'>間</b>與線程<b class='flag-5'>間</b>的<b class='flag-5'>通信</b>方式

    你知道linux socket進程通信是怎樣實現的?

    socket進程通信與網絡通信使用的是統一套接口,只是地址結構與某些參數不同
    發表于 04-23 14:49 ?2783次閱讀
    你知道<b class='flag-5'>linux</b> socket<b class='flag-5'>進程</b><b class='flag-5'>通信</b>是怎樣<b class='flag-5'>實現</b>的?

    Linux進程通信

    進程通信概述進程通信有如下
    發表于 04-02 14:46 ?588次閱讀

    Linux進程通信方式——管道

    管道是Linux進程通信種方式,它把個程序的輸出直接連接到另
    發表于 06-01 09:13 ?1630次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>進程</b><b class='flag-5'>間</b><b class='flag-5'>通信</b>方式——管道

    Linux進程通信方法之管道

    上文中我們介紹了進程通信的方法之:信號,本文將繼續介紹另進程
    的頭像 發表于 05-14 15:47 ?2260次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>進程</b><b class='flag-5'>間</b><b class='flag-5'>通信</b>方法之管道

    進程通信機制有哪些

    比較難,Linux內核提供了多種進程通信機制。 同
    的頭像 發表于 07-21 11:23 ?1324次閱讀
    <b class='flag-5'>進程</b><b class='flag-5'>間</b><b class='flag-5'>通信</b>的<b class='flag-5'>機制</b>有哪些
    主站蜘蛛池模板: 国产福利视频在线观看福利 | 日韩一级精品久久久久 | 久久精品国产男包 | 久久热在线视频精品店 | 十分钟免费观看大全视频 | 8X拨牐拨牐X8免费视频8 | 99视频一区| 国产在线精品亚洲观看不卡欧美 | 男女车车的车车网站W98免费 | 精品人妻伦九区久久AAA片69 | 久久婷婷五月综合色精品首页 | 欧美老少欢杂交另类 | 亚洲伊人久久大香线蕉综合图片 | 国产精品久久国产三级国不卡顿 | https黄视| 精品国产品国语在线不卡丶 | 久久青青无码AV亚洲黑人 | 亚洲精品婷婷无码成人A片在线 | 恋夜直播午夜秀场最新 | 97超碰在线视频人人av | 激情综合色 | 97免费观看视频 | 国产午夜精品不卡观看 | 嘟嘟嘟在线视频免费观看高清中文 | 成年私人影院网站在线看 | 两性午夜刺激爽爽视频 | 久久re这里视频精品15 | 法国剧丝袜情版h级在线电影 | 亚洲你我色 | 伊人久久大香线蕉综合电影网 | 夜夜澡人人爽人人喊_欧美 夜夜骑夜夜欢 | 黄色三级三级三级免费看 | 亚洲精品中文字幕无码A片蜜桃 | 手机在线免费观看毛片 | 欧美极品尿交 | 好爽别插了无码视频 | FREE性丰满白嫩白嫩的HD | 老女人与小伙子露脸对白 | 亚洲国产综合久久久无码色伦 | 嫩草影院地址一地址二 | 日本邪恶少女漫画大全 |

    電子發燒友

    中國電子工程師最喜歡的網站

    • 2931785位工程師會員交流學習
    • 獲取您個性化的科技前沿技術信息
    • 參加活動獲取豐厚的禮品