之前了解c的时候,简单的看过,但是在阅读c源码的时候会突然出现这种。
#一个sds字符串+一个长度,是啥玩意? read(fd, c->querybuf+qblen, readlen);
c中有两种引用->和.。
先看下->
->是指向结构体成员运算符
->所指向的是结构体或对象的首地址
->的用处是使用一个指向,以便访问结构体或对象其内成员
看下.
.是断点符号,不属于运算符
.所指向的是结构体或对象
.的用处是使用一个指向以便访问结构体或对象
噢,了解了,querybuf的首地址+对应的长度,也就是从哪块开始
在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 指针进行一些算术运算
从源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/
和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中还有一些共用体。
将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的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);
/**
/** * 使用__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 **如果觉得本文对你有用,欢迎一键三连哦。**