ipc操作支持映射
This commit is contained in:
@@ -6,7 +6,25 @@
|
||||
#define MSG_BUF_RECV_R_FLAGS 0x02U //!< 接收上次发送数据的接收者
|
||||
#define MSG_BUF_REPLY_FLAGS 0x04U //!<
|
||||
|
||||
#define IPC_MSG_SIZE 96 //!< IPC消息大小
|
||||
#define MAP_BUF_SIZE 16 //!< 映射消息大小
|
||||
#define IPC_USER_SIZE 12 //!< 用户态消息大小
|
||||
|
||||
typedef struct ipc_msg
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
umword_t msg_buf[IPC_MSG_SIZE / WORD_BYTES];
|
||||
umword_t map_buf[MAP_BUF_SIZE / WORD_BYTES];
|
||||
umword_t user[IPC_USER_SIZE / WORD_BYTES];
|
||||
};
|
||||
uint8_t data[MSG_BUG_LEN];
|
||||
};
|
||||
} ipc_msg_t;
|
||||
|
||||
msg_tag_t ipc_bind(obj_handler_t obj, obj_handler_t tag_th, umword_t user_obj);
|
||||
msg_tag_t ipc_wait(obj_handler_t obj, umword_t *user_obj);
|
||||
msg_tag_t ipc_reply(obj_handler_t obj, umword_t len);
|
||||
msg_tag_t ipc_call(obj_handler_t obj, umword_t len);
|
||||
msg_tag_t ipc_reply(obj_handler_t obj, msg_tag_t tag);
|
||||
msg_tag_t ipc_call(obj_handler_t obj, msg_tag_t tag);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include "u_arch.h"
|
||||
#include "u_util.h"
|
||||
typedef unsigned long umword_t;
|
||||
typedef long mword_t;
|
||||
|
||||
|
||||
@@ -43,12 +43,12 @@ msg_tag_t ipc_wait(obj_handler_t obj, umword_t *user_obj)
|
||||
}
|
||||
return msg_tag_init(r0);
|
||||
}
|
||||
msg_tag_t ipc_reply(obj_handler_t obj, umword_t len)
|
||||
msg_tag_t ipc_reply(obj_handler_t obj, msg_tag_t in_tag)
|
||||
{
|
||||
register volatile umword_t r0 asm("r0");
|
||||
|
||||
syscall(syscall_prot_create(IPC_REPLY, IPC_PROT, obj),
|
||||
msg_tag_init4(0, ROUND_UP(len, WORD_BYTES), 0, 0).raw,
|
||||
in_tag.raw,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
@@ -58,12 +58,12 @@ msg_tag_t ipc_reply(obj_handler_t obj, umword_t len)
|
||||
|
||||
return tag;
|
||||
}
|
||||
msg_tag_t ipc_call(obj_handler_t obj, umword_t len)
|
||||
msg_tag_t ipc_call(obj_handler_t obj, msg_tag_t in_tag)
|
||||
{
|
||||
register volatile umword_t r0 asm("r0");
|
||||
|
||||
syscall(syscall_prot_create(IPC_CALL, IPC_PROT, obj),
|
||||
msg_tag_init4(0, ROUND_UP(len, WORD_BYTES), 0, 0).raw,
|
||||
in_tag.raw,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
|
||||
|
||||
int main(int args, char *argv[])
|
||||
{
|
||||
|
||||
while (1)
|
||||
;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,9 @@ int main(int argc, char *args[])
|
||||
thread_test();
|
||||
thread_exit_test();
|
||||
ipc_test();
|
||||
#endif
|
||||
app_test();
|
||||
#endif
|
||||
map_test();
|
||||
while(1);
|
||||
task_unmap(TASK_THIS, TASK_THIS);
|
||||
printf("exit init.\n");
|
||||
|
||||
@@ -62,6 +62,6 @@ void app_test(void)
|
||||
umword_t len;
|
||||
thread_msg_buf_get(THREAD_MAIN, (umword_t *)(&buf), NULL);
|
||||
strcpy(buf, "hello shell.\n");
|
||||
ipc_call(hd_ipc, strlen(buf));
|
||||
ipc_call(hd_ipc,msg_tag_init4(0, ROUND_UP(strlen(buf), WORD_BYTES), 0, 0));
|
||||
printf("test ok\n");
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ static void thread_test_func(void)
|
||||
ipc_wait(ipc_hd, 0);
|
||||
printf("srv recv:%s", buf);
|
||||
hard_sleep();
|
||||
ipc_reply(ipc_hd, strlen(buf));
|
||||
ipc_reply(ipc_hd, msg_tag_init4(0, ROUND_UP(strlen(buf), WORD_BYTES), 0, 0));
|
||||
}
|
||||
printf("thread_test_func.\n");
|
||||
task_unmap(TASK_PROT, th1_hd);
|
||||
@@ -96,7 +96,7 @@ static void thread_test_func2(void)
|
||||
while (1)
|
||||
{
|
||||
strcpy(buf, "I am th2.\n");
|
||||
ipc_call(ipc_hd, strlen(buf));
|
||||
ipc_call(ipc_hd, msg_tag_init4(0, ROUND_UP(strlen(buf), WORD_BYTES), 0, 0));
|
||||
printf("th2:%s", buf);
|
||||
}
|
||||
printf("thread_test_func2.\n");
|
||||
@@ -112,7 +112,7 @@ static void thread_test_func3(void)
|
||||
while (1)
|
||||
{
|
||||
strcpy(buf, "I am th3.\n");
|
||||
ipc_call(ipc_hd, strlen(buf));
|
||||
ipc_call(ipc_hd, msg_tag_init4(0, ROUND_UP(strlen(buf), WORD_BYTES), 0, 0));
|
||||
printf("th3:%s", buf);
|
||||
}
|
||||
printf("thread_test_func2.\n");
|
||||
|
||||
101
mkrtos_user/server/init/src/test/map_test.c
Normal file
101
mkrtos_user/server/init/src/test/map_test.c
Normal file
@@ -0,0 +1,101 @@
|
||||
#include "u_log.h"
|
||||
#include "u_prot.h"
|
||||
#include "u_mm.h"
|
||||
#include "u_factory.h"
|
||||
#include "u_thread.h"
|
||||
#include "u_task.h"
|
||||
#include "u_ipc.h"
|
||||
#include "u_hd_man.h"
|
||||
#include "u_arch.h"
|
||||
#include "u_util.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define DEBUG_IPC_CALL 1
|
||||
|
||||
static umword_t th1_hd = 0;
|
||||
static umword_t th2_hd = 0;
|
||||
static umword_t ipc_hd = 0;
|
||||
|
||||
static char msg_buf0[MSG_BUG_LEN];
|
||||
static char msg_buf1[MSG_BUG_LEN];
|
||||
#define STACK_SIZE 1024
|
||||
static __attribute__((aligned(8))) uint8_t stack0[STACK_SIZE];
|
||||
static __attribute__((aligned(8))) uint8_t stack1[STACK_SIZE];
|
||||
|
||||
static void hard_sleep(void)
|
||||
{
|
||||
|
||||
for (volatile int i; i < 10000000; i++)
|
||||
;
|
||||
}
|
||||
static void thread_test_func(void)
|
||||
{
|
||||
char *buf;
|
||||
umword_t len;
|
||||
ipc_msg_t *ipc_msg;
|
||||
|
||||
thread_msg_buf_get(th1_hd, (umword_t *)(&buf), NULL);
|
||||
ipc_msg = (ipc_msg_t *)buf;
|
||||
ipc_msg->map_buf[0] = handler_alloc();
|
||||
ipc_wait(ipc_hd, 0);
|
||||
printf("srv recv:%s", buf);
|
||||
ulog_write_str(ipc_msg->map_buf[0], "map test success.\n");
|
||||
hard_sleep();
|
||||
ipc_reply(ipc_hd, msg_tag_init4(0, ROUND_UP(strlen(buf), WORD_BYTES), 0, 0));
|
||||
printf("thread_test_func.\n");
|
||||
task_unmap(TASK_PROT, th1_hd);
|
||||
printf("Error\n");
|
||||
}
|
||||
static void thread_test_func2(void)
|
||||
{
|
||||
char *buf;
|
||||
umword_t len;
|
||||
ipc_msg_t *ipc_msg;
|
||||
|
||||
thread_msg_buf_get(th2_hd, (umword_t *)(&buf), NULL);
|
||||
ipc_msg = (ipc_msg_t *)buf;
|
||||
strcpy(ipc_msg->msg_buf, "I am th2.\n");
|
||||
ipc_msg->map_buf[0] = LOG_PROT;
|
||||
ipc_call(ipc_hd, msg_tag_init4(0, ROUND_UP(strlen(ipc_msg->msg_buf), WORD_BYTES), 1, 0));
|
||||
printf("th2:%s", buf);
|
||||
printf("thread_test_func2.\n");
|
||||
task_unmap(TASK_PROT, th2_hd);
|
||||
printf("Error\n");
|
||||
}
|
||||
/**
|
||||
* @brief 启动两个线程并进行ipc测试
|
||||
*
|
||||
*/
|
||||
void map_test(void)
|
||||
{
|
||||
th1_hd = handler_alloc();
|
||||
assert(th1_hd != HANDLER_INVALID);
|
||||
th2_hd = handler_alloc();
|
||||
assert(th2_hd != HANDLER_INVALID);
|
||||
|
||||
msg_tag_t tag = factory_create_ipc(FACTORY_PROT, ipc_hd);
|
||||
assert(msg_tag_get_prot(tag) >= 0);
|
||||
tag = factory_create_thread(FACTORY_PROT, th1_hd);
|
||||
assert(msg_tag_get_prot(tag) >= 0);
|
||||
ipc_bind(ipc_hd, th1_hd, 0);
|
||||
tag = thread_msg_buf_set(th1_hd, msg_buf0);
|
||||
assert(msg_tag_get_prot(tag) >= 0);
|
||||
tag = thread_exec_regs(th1_hd, (umword_t)thread_test_func, (umword_t)stack0 + STACK_SIZE, RAM_BASE());
|
||||
assert(msg_tag_get_prot(tag) >= 0);
|
||||
tag = thread_bind_task(th1_hd, TASK_THIS);
|
||||
assert(msg_tag_get_prot(tag) >= 0);
|
||||
tag = thread_run(th1_hd);
|
||||
|
||||
assert(msg_tag_get_prot(tag) >= 0);
|
||||
tag = factory_create_thread(FACTORY_PROT, th2_hd);
|
||||
assert(msg_tag_get_prot(tag) >= 0);
|
||||
tag = thread_msg_buf_set(th2_hd, msg_buf1);
|
||||
assert(msg_tag_get_prot(tag) >= 0);
|
||||
tag = thread_exec_regs(th2_hd, (umword_t)thread_test_func2, (umword_t)stack1 + STACK_SIZE, RAM_BASE());
|
||||
assert(msg_tag_get_prot(tag) >= 0);
|
||||
tag = thread_bind_task(th2_hd, TASK_THIS);
|
||||
assert(msg_tag_get_prot(tag) >= 0);
|
||||
tag = thread_run(th2_hd);
|
||||
assert(msg_tag_get_prot(tag) >= 0);
|
||||
}
|
||||
@@ -9,4 +9,5 @@ void app_test(void);
|
||||
void mpu_test(void);
|
||||
void printf_test(void);
|
||||
void ipc_test(void);
|
||||
void thread_exit_test(void);
|
||||
void thread_exit_test(void);
|
||||
void map_test(void);
|
||||
344
mkrtos_user/server/path_manager/src/main.bk
Normal file
344
mkrtos_user/server/path_manager/src/main.bk
Normal file
@@ -0,0 +1,344 @@
|
||||
|
||||
#include "u_log.h"
|
||||
#include "u_prot.h"
|
||||
#include "u_mm.h"
|
||||
#include "u_factory.h"
|
||||
#include "u_thread.h"
|
||||
#include "u_task.h"
|
||||
#include "u_util.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <slist.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
typedef enum tree_node_type
|
||||
{
|
||||
TREE_NODE_ENTITY = 0,
|
||||
TREE_NODE_TREE = 1,
|
||||
} tree_node_type_t;
|
||||
|
||||
typedef struct tree_node
|
||||
{
|
||||
char *name; //!< 节点的名字
|
||||
union
|
||||
{
|
||||
slist_head_t list; //!< 双向链表
|
||||
struct
|
||||
{
|
||||
struct tree_node *next_tree; //!< 下一级树
|
||||
struct tree_node *parent; //!< 父节点
|
||||
};
|
||||
};
|
||||
tree_node_type_t type; //!< 节点类型
|
||||
umword_t hlink; //!< 硬链接数量
|
||||
obj_handler_t obj; //!< 目标对象索引号
|
||||
} tree_node_t;
|
||||
|
||||
bool_t tree_node_init(tree_node_t *node, const char *name, tree_node_type_t type)
|
||||
{
|
||||
assert(node);
|
||||
assert(name);
|
||||
char *new_name = strdup(name);
|
||||
if (!new_name)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
node->name = new_name;
|
||||
switch (type)
|
||||
{
|
||||
case TREE_NODE_ENTITY:
|
||||
slist_init(&node->list);
|
||||
break;
|
||||
case TREE_NODE_TREE:
|
||||
node->next_tree = NULL;
|
||||
node->parent = NULL;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
void tree_node_add_raw(tree_node_t *head, tree_node_t *node, tree_node_type_t type)
|
||||
{
|
||||
assert(head);
|
||||
assert(node);
|
||||
switch (type)
|
||||
{
|
||||
case TREE_NODE_ENTITY:
|
||||
slist_add(head, &node->list);
|
||||
break;
|
||||
case TREE_NODE_TREE:
|
||||
head->next_tree = node;
|
||||
head->parent = head;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 比较两个字符串,b2只比较指定长度
|
||||
*
|
||||
* @param b1
|
||||
* @param b2
|
||||
* @param b2len
|
||||
* @return int
|
||||
*/
|
||||
int strcmp_l(const char *b1, const char *b2, size_t b2len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; b1[i] && b2[i] && i < b2len; i++)
|
||||
{
|
||||
if (b1[i] - b2[i] != 0)
|
||||
{
|
||||
return b1[i] - b2[i];
|
||||
}
|
||||
}
|
||||
if (b2len == i)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/**
|
||||
* @brief 在树中找到需要的节点
|
||||
*
|
||||
* @param head
|
||||
* @param name
|
||||
* @param len
|
||||
* @param node
|
||||
* @return tree_node_t*
|
||||
*/
|
||||
tree_node_t *tree_node_find(tree_node_t *head, const char *name, int len, tree_node_type_t node)
|
||||
{
|
||||
tree_node_t *pos;
|
||||
assert(head->type == TREE_NODE_TREE);
|
||||
|
||||
slist_foreach(pos, &head->list, list)
|
||||
{
|
||||
if (pos->type == node &&
|
||||
strcmp_l(pos->name, name, len) == 0)
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef struct mk_file
|
||||
{
|
||||
tree_node_t *node; //!< 打开的node
|
||||
int flags; //!< 操作的标记
|
||||
int mode; //!< 操作的模式
|
||||
int offset; //!< 操作偏移
|
||||
int used; //!< 是否在使用
|
||||
} mk_file_t;
|
||||
#define MK_FILES_NR 8 //!< 最多支持打开多少文件
|
||||
static mk_file_t mk_files[MK_FILES_NR];
|
||||
mk_file_t *mk_file_alloc(int *inx)
|
||||
{
|
||||
//!< TODO:多线程情况下需要加锁
|
||||
for (int i = 0; i < MK_FILES_NR; i++)
|
||||
{
|
||||
if (mk_files[i].used == 0)
|
||||
{
|
||||
mk_files[i].used = 1;
|
||||
*inx = i;
|
||||
return &mk_files[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void mk_file_free(int inx)
|
||||
{
|
||||
mk_files[inx].used = 0;
|
||||
}
|
||||
|
||||
char *pwd = "/"; //! 当前节点
|
||||
static tree_node_t root_node; //!< 根节点
|
||||
static tree_node_t *pwd_node = &root_node; //!< 当前节点
|
||||
|
||||
int path_lookup(tree_node_t *dir, const char *name, int len, tree_node_t **result)
|
||||
{
|
||||
if (len == 2 && name[0] == '.' && name[1] == '.')
|
||||
{
|
||||
if (dir == &root_node) //!< 根目录的上一个就是自己
|
||||
{
|
||||
*result = dir;
|
||||
return 0;
|
||||
}
|
||||
else if (0)
|
||||
{
|
||||
/*TODO:如果是一个挂载点*/
|
||||
}
|
||||
}
|
||||
if (dir->type != TREE_NODE_TREE)
|
||||
{
|
||||
return -ENOTDIR;
|
||||
}
|
||||
*result = tree_node_find(dir, name, len, TREE_NODE_TREE);
|
||||
if (*result == NULL)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
tree_node_t *path_open_dir_namei(
|
||||
tree_node_t *dir,
|
||||
const char *name,
|
||||
char **res_name,
|
||||
int *res_len,
|
||||
int *err)
|
||||
{
|
||||
tree_node_t *cur_node = dir;
|
||||
int inx = 0;
|
||||
int find_len = 0;
|
||||
|
||||
if (cur_node == NULL)
|
||||
{
|
||||
dir = pwd_node;
|
||||
//!< TODO:引用计数+1
|
||||
}
|
||||
|
||||
if (name[inx] == '/' || name[inx] == '\\')
|
||||
{
|
||||
cur_node = &root_node;
|
||||
//!< TODO:引用计数+1
|
||||
inx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_node = pwd_node;
|
||||
//!< TODO:引用计数+1
|
||||
}
|
||||
while (name[inx])
|
||||
{
|
||||
find_len = 0;
|
||||
if (name[inx] != 0 && name[inx] != '/' && name[inx] != '\\')
|
||||
{
|
||||
find_len++;
|
||||
inx++;
|
||||
}
|
||||
*res_len = find_len;
|
||||
*res_name = &name[inx];
|
||||
int ret = path_lookup(cur_node, &name[inx], find_len, &cur_node);
|
||||
if (ret < 0)
|
||||
{
|
||||
*err = -ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
*err = 0;
|
||||
return cur_node;
|
||||
}
|
||||
int path_open_nami(const char *path, int flags, int mode, tree_node_t **res_node)
|
||||
{
|
||||
int err;
|
||||
char *name;
|
||||
int len;
|
||||
int res;
|
||||
tree_node_t *file_node;
|
||||
tree_node_t *node = path_open_dir_namei(NULL, path, &name, &len, &err);
|
||||
|
||||
if (err < 0)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
if (node->type != TREE_NODE_TREE)
|
||||
{
|
||||
return -ENOTDIR;
|
||||
}
|
||||
if (len == 0)
|
||||
{
|
||||
if ((flags & O_WRONLY) || (flags & O_RDWR))
|
||||
{
|
||||
// TOOD:puti(node)
|
||||
return -EISDIR;
|
||||
}
|
||||
*res_node = node;
|
||||
return 0;
|
||||
}
|
||||
if (flags & O_CREAT)
|
||||
{
|
||||
res = path_lookup(node, name, len, &file_node);
|
||||
if (res >= 0)
|
||||
{
|
||||
if (flags & O_EXCL)
|
||||
{
|
||||
// puti(file_node);
|
||||
return -EEXIST;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: 创建新的节点
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res = path_lookup(node, name, len, &file_node);
|
||||
if (res < 0)
|
||||
{
|
||||
// TODO: puti(dir);
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
if (flags & O_TRUNC)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
*res_node = file_node;
|
||||
return res;
|
||||
}
|
||||
int path_open(const char *path, int flags, mode_t mode)
|
||||
{
|
||||
int inx = 0;
|
||||
mk_file_t *file = mk_file_alloc(&inx);
|
||||
if (!file)
|
||||
{
|
||||
return -EMFILE;
|
||||
}
|
||||
tree_node_t *node;
|
||||
|
||||
int res = path_open_nami(path, flags, mode, &node);
|
||||
if (res < 0)
|
||||
{
|
||||
mk_file_free(inx);
|
||||
return res;
|
||||
}
|
||||
/*TODO:调用打开接口*/
|
||||
if (msg_tag_get_val(task_obj_valid(TASK_THIS, node->obj)) <= 0)
|
||||
{
|
||||
/*TODO:obj已经无效,删除这个文件节点*/
|
||||
mk_file_free(inx);
|
||||
return -ECANCELED;
|
||||
} else {
|
||||
// 映射给open的操作者
|
||||
}
|
||||
file->flags = flags;
|
||||
file->mode = mode;
|
||||
file->offset = 0;
|
||||
file->node = node;
|
||||
return inx;
|
||||
}
|
||||
//路径管理器大纲
|
||||
//路径管理器,所有的非固化存储的资源
|
||||
//支持mount其它文件系统,其它文件系统也是一个服务对象
|
||||
//支持mount单个服务对象。
|
||||
//打开一个文件时,首先在路径管理器中找到文件系统服务的对象,
|
||||
//然后调用文件系统服务对象的open接口打开文件,该文件系统返回一个句柄。
|
||||
//之后的操作都直接对文件系统服务对象进行操作,不在经过路径管理器。
|
||||
|
||||
//路径管理器也可以映射其它任意对象,但这些对象可能不具备读写等操作,具体操作由使用者负责。
|
||||
|
||||
int main(int argc, char *args[])
|
||||
{
|
||||
// printf("shell>\n");
|
||||
ulog_write_str(LOG_PROT, "MKRTOS:\n");
|
||||
while (1)
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
@@ -12,7 +12,7 @@ int main(int argc, char *args[])
|
||||
{
|
||||
ulog_write_str(LOG_PROT, "MKRTOS:\n");
|
||||
ipc_wait(12, 0);
|
||||
ipc_reply(12, 0);
|
||||
ipc_reply(12, msg_tag_init4(0, 0, 0, 0));
|
||||
char *buf;
|
||||
umword_t len;
|
||||
thread_msg_buf_get(THREAD_MAIN, (umword_t *)(&buf), NULL);
|
||||
|
||||
Reference in New Issue
Block a user