ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

阅读redis源码的时候一些c知识

2022-01-02 21:01:10  阅读:219  来源: 互联网

标签:__ int void 知识 redis 源码 cond pthread mutex


c中的引用

之前了解c的时候,简单的看过,但是在阅读c源码的时候会突然出现这种。

#一个sds字符串+一个长度,是啥玩意?
read(fd, c->querybuf+qblen, readlen);

c中有两种引用->和.。

先看下->

  • ->是指向结构体成员运算符

  • ->所指向的是结构体或对象的首地址

  • ->的用处是使用一个指向,以便访问结构体或对象其内成员

看下.

  • .是断点符号,不属于运算符

  • .所指向的是结构体或对象

  • .的用处是使用一个指向以便访问结构体或对象

噢,了解了,querybuf的首地址+对应的长度,也就是从哪块开始

void 关键字,表示没有值

在java中含义很明确,就是修饰方法无返回值,在c中用在不同的地方概念也不同。

表示无返回值

# 表示无返回值
void add(int x,int y);

表示无入参

# 表示无入参
int free(void);

指向指针

一个void* 类型的指针,表示无数据类型的指针,可以指向任意类型的数据

void *memcpy(void *dst, const void *src, size_t n)

int *a;
void *p;
p=a;
# void指针赋值给其他类型的指针,需要强制类型转换
a=(int *)p

# 表示malloc返回的void*指针指向的是int类型
(int *)malloc(1024)


在 ANSI C 标准中,不允许对 void 指针进行一些算术运算

字符串操作

字符复制 memcpy

从源src所指的内存地址的起始位置拷贝n个支付到目标dst所指的内存地址的起始位置。

语法:
void *memcpy(void *dst, const void *src, size_t n)
- dst 用于存储复制内容的目标数组,类型强制转换为 void* 指针
- src 要复制的数据源,类型强制转换为 void* 指针
- n  要复制的直接长度

返回dst的指针

示例:

/**
 * @brief sds 拼接
 * @param s 当前的sds
 * @param t 需要从哪拷贝的指针,大部分都是一个char,部分首地址+长度
 * @param len 需要拷贝的长度
 * @return sds 
 */
sds sdscatlen(sds s, const void *t, size_t len) {
    //获取原sds的长度
    size_t curlen = sdslen(s);
    //空间预分配,如果预留的空间够len,不处理,不够,会调整s的类型
    s = sdsMakeRoomFor(s,len);
    if (s == NULL) return NULL;
    //将t中复制len长度到s首地址+curlen的位置
    memcpy(s+curlen, t, len);
    sdssetlen(s, curlen+len);
    //拼接\0表示字符串的结尾
    s[curlen+len] = '\0';
    return s;
}

引用示例:
# 指针+偏移量
sdscatlen(c->pending_querybuf, c->querybuf+qblen,nread);
# 字符
sdscatlen(o,"\n",1)


举例说明:

char s1[] ="https://www.5ycode.com/";
char t1[] ="5ycode";
int curlen1 = strlen(s1);
int len1=6;
printf("s1 memcpy before :%s \n",s1);
memcpy(s1, t1, len1);
printf("s1 memcpy after :%s \n",s1);

输出:
s1 memcpy before :https://www.5ycode.com/ 
s1 memcpy after :5ycode//www.5ycode.com/ 
    

字符复制memove

和memcpy差不多。

语法:
void *memmove(void *dst, const void *src, size_t len)
- dst 用于存储复制内容的目标数组,类型强制转换为 void* 指针
- src 要复制的数据源,类型强制转换为 void* 指针
- n  要复制的直接长度

区别:

  • 正常情况下memcpy 和memove的功能一样

  • 当dst和src的内存地址有重合的时候,memove能正确处理,memcpy不保证

  • 由于正确性的保证,memove的效率相对memcpy的效率较低;

在redis中大量的在使用memcpy,因为大部分都是先申请空间,有些地方用到了memove,其中redis中还有一些共用体。

字符填充memset

将b中的前len个字符用c替代。

作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清空操作的最快方法,c和b的内存区域不能重叠,且b中必须有足够空间来存储c

#语法
void *memset(void *b, int c, size_t len)

  • b 指向要填充的内存块

  • c 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式

  • len 要被设置为c的b的字符长度

在redis中的示例

  memset(server.cluster->slots_keys_count,0,sizeof(server.cluster->slots_keys_count));

redis中的线程操作

在redis的bio.c中有许多关于锁的操作,在redis6中也是

线程创建相关
pthread_create 创建线程
pthread_attr_init  初始化线程属性
pthread_attr_getstacksize 获取线程栈大小
pthread_attr_setstacksize 设置线程栈大小

线程互斥锁相关

pthread_mutex_init  初始化一个互斥锁
pthread_mutex_lock  获取互斥锁(上锁)
pthread_mutex_trylock 尝试上锁
pthread_mutex_unlock 解除互斥锁
pthread_mutex_destroy 销毁锁

条件变量
pthread_cond_init  初始化条件变量,只有等待这个条件发生线程才继续执行
pthread_cond_wait  等待条件变量的信号或广播
pthread_cond_timedwait  在指定时间内等待条件变量的信号或广播
pthread_cond_signal 唤醒一个条件变量上的阻塞
pthread_cond_broadcast 唤醒所有被阻塞的线程
pthread_cond_destroy 销毁条件变量

设置线程对cancel信号的反应
pthread_setcancelstate
pthread_setcanceltype

两组:
PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_ASYNCHRONOUS 表示接收到取消信号后,立即取消(退出)
PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_DEFFERED  表示接收到取消信号后继续运行,直到下一个取消点再退出

语法

/**
 * 创建线程。
 * @param thread 线程id
 * @param attr 属性,一般可设置为NULL
 * @param start_routine 执行在子线程的函数
 * @param arg 传递到子线程函数的参数
 * @return 如果成功返回0,失败返回错误码
 */
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
          
/**
 * 等待线程退出
 * 让调用这个方法的线程等待thread退出。如果retval不是NULL,thread的退出状态将存放到retval中。
 * @param thread 线程id
 * @param retval 获取线程函数返回值,如果不需要可以填NULL
 * @return 如果成功返回0,失败返回错误码
 */
int pthread_join(pthread_t thread, void **retval);



/**

  • 初始化一个锁。
  • @param __mutex 锁
  • @param __mutexattr 属性
  • @return 如果成功返回0,失败返回错误码
    */
    int pthread_mutex_init (pthread_mutex_t __mutex,const pthread_mutexattr_t __mutexattr);
    /
  • 销毁一个锁。
  • @param __mutex 锁
  • @return 如果成功返回0,失败返回错误码
    /
    int pthread_mutex_destroy (pthread_mutex_t __mutex);
    /
  • 上锁。
  • @param mutex 锁
  • @return 如果成功返回0,失败返回错误码
    /
    int pthread_mutex_lock(pthread_mutex_t mutex);
    /
  • 尝试上锁。
  • @param mutex 锁
  • @return 如果成功返回0,失败返回错误码
    /
    int pthread_mutex_trylock(pthread_mutex_t mutex);
    /
  • 解锁。
  • @param __mutex 锁
  • @return 如果成功返回0,失败返回错误码
    */
    int pthread_mutex_unlock (pthread_mutex_t *__mutex);
/**
 * 使用__cond_attr初始化条件变量,__cond_attr设置为NULL,将使用默认属性初始化条件变量。
 * @param __cond 要初始化的条件变量
 * @param __cond_attr 属性
 * @return 如果成功返回0,失败返回错误码
 */
int pthread_cond_init (pthread_cond_t *__cond, 
                       const pthread_condattr_t *__cond_attr);

/**
 * 催毁条件变量。
 * @param __cond 要催毁的条件变量
 * @return 如果成功返回0,失败返回错误码
 */
int pthread_cond_destroy (pthread_cond_t *__cond);

/**
 * 唤醒一个用条件变量__cond等待的线程。
 * @param __cond 目标条件变量
 * @return 如果成功返回0,失败返回错误码
 */
int pthread_cond_signal (pthread_cond_t *__cond);

/* Wake up all threads waiting for condition variables COND.  */
/**
 * 唤醒所有用条件变量__cond等待的线程。
 * @param __cond 目标条件变量
 * @return 如果成功返回0,失败返回错误码
 */
int pthread_cond_broadcast (pthread_cond_t *__cond);

/**
 * 等待条件变量__cond的一个信号或者广播。调用该函数之前你应该确保已经用
 * __mutex上锁。
 * @param __cond 目标条件变量
 * @param __mutex 配合__cond的锁
 * @return 如果成功返回0,失败返回错误码
 */
int pthread_cond_wait (pthread_cond_t * __cond,pthread_mutex_t * __mutex);
/**
 * 在指定时间内等待条件变量__cond的一个信号或者广播,调用该函数之前你应该确保已经用
 * __mutex上锁。
 * @param __cond 目标条件变量
 * @param __mutex 配合__cond的锁
 * @param __abstime 绝对时间
 * @return
 */
int pthread_cond_timedwait (pthread_cond_t * __cond,  pthread_mutex_t * __mutex, const struct timespec * __abstime);

```

一些结构体

```
typedef struct{
   int  detachstate;   //线程的分离状态
   int  schedpolicy;  //线程调度策略
   structsched_param   schedparam;  //线程的调度参数
   int  inheritsched;  //线程的继承性
   int  scope;       //线程的作用域
   size_t   guardsize;   //线程栈末尾的警戒缓冲区大小
   int   stackaddr_set;
   void*   stackaddr;   线程栈的位置
   size_t   stacksize;    线程栈的大小
}pthread_attr_t;


```

参考文章: 

https://www.runoob.com/cprogramming/c-tutorial.html

https://codbo.cn/blog-12.html

https://blog.csdn.net/chengonghao/article/details/51779279

https://segmentfault.com/q/1010000016389831/a-1020000016390662

**如果觉得本文对你有用,欢迎一键三连哦。**

标签:__,int,void,知识,redis,源码,cond,pthread,mutex
来源: https://blog.csdn.net/f80407515/article/details/122280622

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有