Linux 下API的实现
作者: 韩大卫@ 吉林师范大学
驱动工程师工作内容之一就是向上层应用端提供API,这个API完成并封装了全部的与硬件芯片的I/O操作。
本问简单的说明了一个实现API函数的全部过程。
总体上看分为:
1,用户API
2,用户中间层(与底层通信)
3,底层中间层(寻找对应的驱动函数)
4, 驱动函数
5, CPU读写I/O端口。
我们主要的工作就是这个驱动部分
这个驱动函数功能是:将数据包装成kernel 中可操作的结构体, 按既有的通信方式发送给CPU,
这种通信方式就是通过总线了。可以是I2C等等。
最后,CPU返回执行结构,驱动函数再返回给用户层。
再将这些API 包装成库, 这样,用户层的程序就可以直接引用了。
下面的API功能是是: 统计交换芯片的接口速率。
Test/main.c 是一个测试程序, API 和API 的底层驱动的实现文件和头文件都在下面的代码中,
另外,用户层与底层之间的通信,使用的是socket ,这是相比与共享内存等最合适最高效的方式。
路径如下: 用户层API--- 中间层(socket)----| -----驱动中间层(socket)---(驱动函数)
这不是完整的程序,只是程序中的骨干部分。
如果需要全部的程序,请联系作者handawei@jusontech.com
***** ********************
转载请务必表明出处。
********* ***************************
在test/main.c 中:
#include "inc/jas.h"
#include <jas_sw_cmd_api.h>
#include <jas_cmd_cli_api.h>
#include <jas_frm_cmd_api.h>
在 inc/cmd_api/jas_sw_cmd_api.h 中:
int jas_sw_intf_cntr_rate_cal(int dev_id, int intf_id, jas_intf_eth_rate_t *cntr);
//这就是用户层使用的API
./libjascmd/jas_cmd_cli_api.h 中:
int jas_cmd_cli_api_send_msg(struct jas_cmd_api_cmd_msg tmsg);
int jas_cmd_cli_api_recv_msg(void *data, uint32_t size);
在Main.c 中的 jas_sw_intf_cntr_rate_cal()定义在:
jas_api/switch/sw_cmd_api.c 中:
int jas_sw_intf_cntr_rate_cal(int dev_id, int intf_id, jas_intf_eth_rate_t *data){
int ret = JAS_SUCCESS;
if(data == NULL)
return JAS_INV_ARG;
ret = jas_cmd_sw_api_intf_cntr_rate_cal(dev_id, intf_id, data);
if(ret < 0)
return ret;
return ret;
}
jas_cmd_sw_api_intf_cntr_rate_cal
这个函数是一个中间层,介于用户层和驱动层之间, 它的声明是在:
libjascmd/jas_cmd_sw_api.h 中:
int jas_cmd_sw_api_intf_cntr_rate_cal(uint8_t dev_id, uint8_t intf_id, jas_intf_eth_rate_t *jas_cntr_data);
定义是在 ibjascmd/jas_cmd_sw_api.c 中:
int jas_cmd_sw_api_intf_cntr_rate_cal(uint8_t dev_id, uint8_t intf_id, jas_intf_eth_rate_t *jas_cntr_data){
int ret = JAS_SUCCESS;
struct jas_cmd_api_cmd_msg msg;
msg.dev_id = dev_id;
msg.intf_id = intf_id;
msg.cmd = SW_INTF_CNTR_RATE_CAL;
msg.dev_type = JAS_CMD_SWITCH;
ret = jas_cmd_cli_api_send_msg(msg);
if (ret < 0) {
return JAS_SET_ERROR;
}
ret = jas_cmd_cli_api_recv_msg(jas_cntr_data, (uint32_t)sizeof(jas_intf_eth_rate_t));
if(ret < 0) {
return ret;
}
return ret;
}
通过使用socket ,发送和接受msg . 实现与驱动层的通信。
那么,socket的接受端是在哪里?
可以通过 grep -rn “SW_INTF_CNTR_RATE_CAL” 的方式,查找出相应的位置。
结果如下:
在libjascmd/jas_cmd_cli_api.c 中:
发现了 case SW_INTF_CNTR_RATE_CAL
进入这个文件中, 就可以找到这个socket 的接受端, 函数如下:
int jas_cmd_cli_serv_check_client(cmdStreamPTR streamP, char *buff, uint32_t length){
socketStreamPTR stream = (socketStreamPTR)streamP;
if(length == 0)
return JAS_SUCCESS;
if(strncmp(buff, "@@JAS_CMD_API", 12) == 0){
write(stream->socket, "Connected!", 10);
return JAS_SUCCESS;
}
if((length != sizeof(struct jas_cmd_api_cmd_msg)) || (strncmp(buff, "########", 8) != 0)){
sys_err("%s, %d, Get Error Buffer: %s, length: %d(%d)\n", __func__, __LINE__, buff, length, sizeof(struct jas_cmd_api_cmd_msg));
return JAS_FAILURE;
}
jas_cmd_cli_serv_run_cmd(streamP, buff);
return 0;
}
进入jas_cmd_cli_serv_run_cmd
int jas_c
作者: 韩大卫@ 吉林师范大学
驱动工程师工作内容之一就是向上层应用端提供API,这个API完成并封装了全部的与硬件芯片的I/O操作。
本问简单的说明了一个实现API函数的全部过程。
总体上看分为:
1,用户API
2,用户中间层(与底层通信)
3,底层中间层(寻找对应的驱动函数)
4, 驱动函数
5, CPU读写I/O端口。
我们主要的工作就是这个驱动部分
这个驱动函数功能是:将数据包装成kernel 中可操作的结构体, 按既有的通信方式发送给CPU,
这种通信方式就是通过总线了。可以是I2C等等。
最后,CPU返回执行结构,驱动函数再返回给用户层。
再将这些API 包装成库, 这样,用户层的程序就可以直接引用了。
下面的API功能是是: 统计交换芯片的接口速率。
Test/main.c 是一个测试程序, API 和API 的底层驱动的实现文件和头文件都在下面的代码中,
另外,用户层与底层之间的通信,使用的是socket ,这是相比与共享内存等最合适最高效的方式。
路径如下: 用户层API--- 中间层(socket)----| -----驱动中间层(socket)---(驱动函数)
这不是完整的程序,只是程序中的骨干部分。
如果需要全部的程序,请联系作者handawei@jusontech.com
***** ********************
转载请务必表明出处。
********* ***************************
在test/main.c 中:
#include "inc/jas.h"
#include <jas_sw_cmd_api.h>
#include <jas_cmd_cli_api.h>
#include <jas_frm_cmd_api.h>
在 inc/cmd_api/jas_sw_cmd_api.h 中:
int jas_sw_intf_cntr_rate_cal(int dev_id, int intf_id, jas_intf_eth_rate_t *cntr);
//这就是用户层使用的API
./libjascmd/jas_cmd_cli_api.h 中:
int jas_cmd_cli_api_send_msg(struct jas_cmd_api_cmd_msg tmsg);
int jas_cmd_cli_api_recv_msg(void *data, uint32_t size);
在Main.c 中的 jas_sw_intf_cntr_rate_cal()定义在:
jas_api/switch/sw_cmd_api.c 中:
int jas_sw_intf_cntr_rate_cal(int dev_id, int intf_id, jas_intf_eth_rate_t *data){
int ret = JAS_SUCCESS;
if(data == NULL)
return JAS_INV_ARG;
ret = jas_cmd_sw_api_intf_cntr_rate_cal(dev_id, intf_id, data);
if(ret < 0)
return ret;
return ret;
}
jas_cmd_sw_api_intf_cntr_rate_cal
这个函数是一个中间层,介于用户层和驱动层之间, 它的声明是在:
libjascmd/jas_cmd_sw_api.h 中:
int jas_cmd_sw_api_intf_cntr_rate_cal(uint8_t dev_id, uint8_t intf_id, jas_intf_eth_rate_t *jas_cntr_data);
定义是在 ibjascmd/jas_cmd_sw_api.c 中:
int jas_cmd_sw_api_intf_cntr_rate_cal(uint8_t dev_id, uint8_t intf_id, jas_intf_eth_rate_t *jas_cntr_data){
int ret = JAS_SUCCESS;
struct jas_cmd_api_cmd_msg msg;
msg.dev_id = dev_id;
msg.intf_id = intf_id;
msg.cmd = SW_INTF_CNTR_RATE_CAL;
msg.dev_type = JAS_CMD_SWITCH;
ret = jas_cmd_cli_api_send_msg(msg);
if (ret < 0) {
return JAS_SET_ERROR;
}
ret = jas_cmd_cli_api_recv_msg(jas_cntr_data, (uint32_t)sizeof(jas_intf_eth_rate_t));
if(ret < 0) {
return ret;
}
return ret;
}
通过使用socket ,发送和接受msg . 实现与驱动层的通信。
那么,socket的接受端是在哪里?
可以通过 grep -rn “SW_INTF_CNTR_RATE_CAL” 的方式,查找出相应的位置。
结果如下:
在libjascmd/jas_cmd_cli_api.c 中:
发现了 case SW_INTF_CNTR_RATE_CAL
进入这个文件中, 就可以找到这个socket 的接受端, 函数如下:
int jas_cmd_cli_serv_check_client(cmdStreamPTR streamP, char *buff, uint32_t length){
socketStreamPTR stream = (socketStreamPTR)streamP;
if(length == 0)
return JAS_SUCCESS;
if(strncmp(buff, "@@JAS_CMD_API", 12) == 0){
write(stream->socket, "Connected!", 10);
return JAS_SUCCESS;
}
if((length != sizeof(struct jas_cmd_api_cmd_msg)) || (strncmp(buff, "########", 8) != 0)){
sys_err("%s, %d, Get Error Buffer: %s, length: %d(%d)\n", __func__, __LINE__, buff, length, sizeof(struct jas_cmd_api_cmd_msg));
return JAS_FAILURE;
}
jas_cmd_cli_serv_run_cmd(streamP, buff);
return 0;
}
进入jas_cmd_cli_serv_run_cmd
int jas_c