#include <linux/version.h>
#include <linux/module.h>MODULE_DESCRIPTION("EB V5 Device Virtual IO Driver.");
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <pthread.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/time.h>
#include <signal.h>
#include <semaphore.h>
#include <errno.h>
#include <sys/ipc.h>
/***********************************************
val : v/p信号量的初始值
return : semid
***********************************************/
int my_sem_init(int val)
{
int sem;
sem = semget(IPC_PRIVATE, 1, 0600);
if (sem ==-1) {
printf("\nsemget failed\n");
//exit(1);
return 0;
}
semctl(sem, 0, SETVAL, val);
return sem;
}
/*****************************************
semid:v/p信号量id
n: 0 单信号量 >0 多信号量
******************************************/
void my_sem_lock(int semid, int n)
{
struct sembuf op;
op.sem_num = n;
op.sem_op = -1;
op.sem_flg = 0;
while (semop(semid, &op, 1) < 0) {
if (errno != EINTR) {
printf("\nmy_sem_lock semop()\n");
//exit(1);
return ;
}
}
return;
}
/*****************************************
semid:v/p信号量id
n: 0 单信号量 >0 多信号量
return:-1 错误返回
-2 没有信号量可用
0 成功
******************************************/
int my_sem_trylock(int semid, int n)
{
struct sembuf op;
op.sem_num = n;
op.sem_op = -1;
op.sem_flg = IPC_NOWAIT;
while (semop(semid, &op, 1) < 0) {
if (errno != EINTR) {
if (errno == EAGAIN) {
printf("\nmy_sem_trylock error\n");
return -1;
}
printf("\nmy_sem_trylock no sem\n");
return -2;
}
}
return 0;
}
void my_sem_unlock(int semid, int n)
{
struct sembuf op;
int ret;
op.sem_num = n;
op.sem_op = +1;
op.sem_flg = 0;
do {
ret = semop(semid, &op, 1);
} while (ret < 0 && errno == EINTR);
return;
}
#define EB_ISAP5000_DEVICE_NAME "/dev/isap5000_vio"
#define EB_ISAP5000_MAP_SIZE (1000 * 4096)
typedef struct{
int semid[20];
int sival[20];
}eb_dev_t;
eb_dev_t *ptr;
void *ebf_dev_map_init(void)
{
int fd = -1;
void *pm;
fd = open(EB_ISAP5000_DEVICE_NAME,O_RDWR);
if(fd < 0){
printf("open failure %d\n",fd);
return NULL;
}
pm = mmap(NULL, EB_ISAP5000_MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(pm == MAP_FAILED){
printf("mmap failure\n");
return NULL;
}
return pm;
}
int chaild_progress( eb_dev_t *ptr)
{
int i;
while(1){
for(i=0;i<20;i++){
printf("other %d %d\n",i,ptr->sival[i]);
my_sem_lock(ptr->semid[i], 0);
ptr->sival[i] = i;
sleep(2);
printf("chaild %d %d\n",i,ptr->sival[i]);
my_sem_unlock(ptr->semid[i], 0);
}
}
return 0;
}
int other_progress( eb_dev_t *ptr)
{
int i;
while(1){
for(i=0;i<20;i++){
printf("chaild %d %d\n",i,ptr->sival[i]);
my_sem_lock(ptr->semid[i], 0);
ptr->sival[i] = 20-i;
sleep(1);
printf("other %d %d\n",i,ptr->sival[i]);
my_sem_unlock(ptr->semid[i], 0);
}
}
return 0;
}
void ebf_sem_init(void)
{
int i;
for(i=0;i<20;i++){
ptr->semid[i] = my_sem_init(1);
printf("\nsemget %d\n",i);
}
}
int main()
{
pid_t pid;
ptr = (eb_dev_t *)ebf_dev_map_init();
if(NULL == ptr){
printf("dev mmap failure\n");
return -1;
}
memset(ptr,0,sizeof(eb_dev_t));
ebf_sem_init();
pid = fork();
if(pid==0){
chaild_progress(ptr);
}
other_progress(ptr);
return 0;
}
在ubunto终端命令行上操作:
切换到root用户:su
apt-get install linux-source
在/usr/src/下会有linux-source-3.2.0内核源码 我的版本是3.2.0
cd /usr/src/linux-source-3.2.0
把上面的char_mmap.c拷贝到 当前目录下的drivers/char/下
vi drivers/char/Kconfig
在menu “Character devices”下添加下面内容
config CHARMMP
tristate “Don't need something support”
help
wellcome my char mmap device driver
vi drivers/char/Makefile
在开头添加下面内容
obj-m += char_mmap.o