os_adapter.c代码分析
本篇主要分析模块一中trans_service目录下tcp_socket.c代码。
文件路径(模块一\communication_softbus_lite- master\trans_service\source\utils\message.c)
一、背景知识
os_adapter相关前缀理论部分已经在队友博客中解释(点击此处查看理论部分)
二、代码分析
软总线模块中os_adapter目录为操作系统接口适配层,其中L0和L1两个目录下各有一个os_adapter.c文件,二者功能函数基本一致,不同点在于适用环境不同,下面主要分析L1下面os_adapter.c文件。
1.初始化互斥锁
mutexinit函数用来初始化互斥锁,基于pthread_mutex_init()函数。
MutexId MutexInit(void)//初始化互斥锁
{
pthread_mutex_t *mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
//使用malloc函数动态申请内存空间
if (mutex == NULL) {
return NULL;
//申请失败函数返回NULL
}
(void)pthread_mutex_init(mutex, NULL);
//该函数用于C函数的多线程编程中,互斥锁的初始化。
return (MutexId)mutex;
}
2.互斥体加锁
MutexLock函数用来为互斥体进行加锁,将参数指定的对象进行加锁,避免被其他进程调用读取。
基于pthread_mutex_lock(),该函数锁住由mutex指定的mutex 对象。如果mutex已经被锁住,调用这个函数的线程阻塞直到mutex可用为止。这跟函数返回的时候参数mutex指定的mutex对象变成锁住状态, 同时该函数的调用线程成为该mutex对象的拥有者。
void MutexLock(MutexId mutex)
{
if (mutex == NULL) {
return;
}
pthread_mutex_lock((pthread_mutex_t *)mutex);
//锁住由mutex指定的mutex 对象。
}
3.互斥体释放
MutexUnLock函数用来释放互斥体指向对象上面的锁,基于pthread_mutex_unlock() 函数。
pthread_mutex_unlock()可释放mutex引用的互斥锁对象。互斥锁的释放方式取决于互斥锁的类型属性。 如果调用pthread_mutex_unlock()时有多个线程被mutex对象阻塞,则互斥锁变为可用时调度策略可确定获取该互斥锁的线程。 对于PTHREAD_MUTEX_RECURSIVE类型的互斥锁,当计数达到零并且调用线程不再对该互斥锁进行任何锁定时,该互斥锁将变为可用。
void MutexUnlock(MutexId mutex)//释放互斥体
{
if (mutex == NULL) {
return;
}
pthread_mutex_unlock((pthread_mutex_t *)mutex);
//释放有参数mutex指定的mutex对象的锁。
}
4.关闭套接字函数
void CloseSocket(int *fd)
{
if (fd == NULL) {
return;
}
if (*fd >= 0) {
close(*fd);
//传入的正值对应的套接字接口关闭
*fd = -1;
}
//关闭socket中套接字连接
}
5.创建消息队列
CreateMsgQue() 函数用来创建一个消息队列。
参数详解
- const char *queueName :队列名
- unsigned short len:每个消息的最大字节数
- unsigned int *queueID:队列的ID编号
- unsigned int flags:消息队列标志,表示是否堵塞
- unsigned short maxMsgSize:消息队列中每个消息的最大字节数
int CreateMsgQue(const char *queueName,//创建一个消息队列
unsigned short len, unsigned int *queueID,
unsigned int flags, unsigned short maxMsgSize)
{
if (queueName == NULL || queueID == NULL) {
return -1;
}
struct mq_attr newAttr = {0};
newAttr.mq_flags = flags;
newAttr.mq_maxmsg = len;
newAttr.mq_msgsize = maxMsgSize;
int mqd = mq_open(queueName, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR, &newAttr);
//mq_open函数用来创建一个消息队列,成功返回队列描述符,失败-1
if (mqd < 0) {
return -1;
//创建失败,函数返回-1推出
}
*queueID = mqd;//将队列id指向创建的消息队列
return 0;
}
6.写消息队列(发送)
WriteMsgQue(unsigned int queueID, const void *bufferAddr , unsigned int bufferSize) 函数用来发送消息并将消息写进队列。基于mq_send()函数。
函数参数详解:
- unsigned int queueID:队列编号ID
- const void *bufferAddr:存放消息的缓冲区地址
- unsigned int bufferSize:消息大小
int WriteMsgQue(unsigned int queueID,
const void *bufferAddr, unsigned int bufferSize)
{
if (bufferAddr == NULL) {
return -1;
}
int ret = mq_send(queueID, bufferAddr, bufferSize, 0);
//将bufferAddr指向的内容以bufferSize大小发送至对应消息队列,发送成功返回0,否则返回非0值
//进程在打开消息队列后,可以使用mq_send函数发送消息。
if (ret != 0) {
return -1;
//发送失败函数返回-1并退出
}
return 0;
}
7.读取消息队列
读取消息函数ReadMsgQue(),基于mq_receive()函数从消息队列中读取消息.
参数详解:
- unsigned int queueID:队列编号ID
- void *bufferAddr:存放消息的缓冲区地址
- unsigned int bufferSize:消息大小
int ReadMsgQue(unsigned int queueID,//从消息队列中读取消息
void *bufferAddr, unsigned int *bufferSize)
{
if (bufferAddr == NULL || bufferSize == NULL) {
return -1;
}
unsigned int readSize = *bufferSize;
unsigned int receiveSize = mq_receive(queueID, bufferAddr, readSize, 0);//从消息队列中获取消息
//调用 mq_receive 时总是返回队列中 最高优先级的最早消息。函数返回值为读取到的字节数
if (receiveSize != readSize) {
return -1;
//读取字节数和传入字节数不相等就退出函数,返回-1
}
*bufferSize = receiveSize;//将缓冲区大小置为接受到的数据大小范围
return 0;
}
8.删除消息队列
DeleteMsgQue(unsigned int queueID) 基于mq_close()函数关闭消息队列
int DeleteMsgQue(unsigned int queueID)//用来删除/关闭消息队列
{
return mq_close(queueID);
//函数会断开消息队列描述符 和 与之对应消息队列间的连接.
}
9.检查用户权限
SoftBusCheckPermission(const char* permissionName) 函数用来检查用户的权限许可。
该函数中用到安卓API中CheckSelfPermission()函数,专门用来检查用户权限
int SoftBusCheckPermission(const char* permissionName)
//用来检查用户权限
{
if (permissionName == NULL) {
return -1;
}
if (CheckSelfPermission(permissionName) != GRANTED) {
//CheckSelfPermission用来检查权限,成功则返回GRANTED对应值
SOFTBUS_PRINT("[SOFTBUS] CheckSelfPermission fail\n");
return -1;
//检查失败输出提示并返回-1
}
return 0;
}
以上为os_adapter.c代码的分析,感谢阅读和点赞。理论部分和头文件请戳这里