当前位置: 首页 > wzjs >正文

html5制作网站开发专业的网络推广

html5制作网站开发,专业的网络推广,前端兼职平台的行业前景,动态网站开发是什么书知识点1【信号量概述】 信号量是广泛用于进程和线程间的同步和互斥。信号量的本质 是一个非负的整数计数器,它被用来控制对公共资源的访问 当信号量值大于0的时候,可以访问,否则将阻塞。 PV原语对信号量的操作,一次P操作使信号…

知识点1【信号量概述】

信号量是广泛用于进程和线程间的同步和互斥。信号量的本质 是一个非负的整数计数器,它被用来控制对公共资源的访问

当信号量值大于0的时候,可以访问,否则将阻塞。

PV原语对信号量的操作,一次P操作使信号量减一,一次V操作使信号量加一。

信号量的类型sem_t

信号量用于互斥:不管多少个任务互斥,只需要一个信号量,信号量应初始化为1

先P操作,再V操作

大家看上面这张图,若任务A抢到该任务量,信号量被初始化为1,由于先P(减一),导致其他线程(进程)被阻塞,实现互斥的功能,然后执行任务A,V操作(加一),其他任务抢锁,循环上面的过程。

信号量用于同步:有多少个任务,就需要多少个信号量,最先执行的任务对应的信号量为1,其他信号量全部为0

下面介绍一下流程

每个任务先P自己,然后V下一个要执行的任务的信号量

详细介绍:

如图,我们先将sem1初始化1,任务A执行P操作,其他任务被阻塞,执行任务A函数体,任务A结束后,执行要执行任务sem2的V操作,又由于sem1的值为0,即使有循环,也不需要担心A任务继续执行

知识点2【信号量的API】

1、初始化信号量sem_init()

  • 函数介绍

    #include <semaphore.h>
    int sem_init(sem_t *sem, int pshared, unsigned int value);
    

    函数功能:

    创建一个信号量并初始化它的值。一个无名信号在被使用前必须先初始化

    参数:

    sen:信号量的地址

    pshared:

    等于0,信号量在线程间共享

    非0:信号量在进程间共享

    value:信号量的初始值

    返回值:

    成功:0

    失败:-1

2、信号量减一 P操作 sem_wait()

  • 函数介绍

    #include <semaphore.h>
    int sem_wait(sem_t *sem); 
    

    函数功能:

    将信号量减一。如果信号量为0,则阻塞,大于0则可以减一

    参数:

    信号量的地址。

    返回值:

    成功:0

    失败:-1

    int sem_trywait(sem_t *sem);*
    

    函数功能:

    尝试将信号量减一,如果信号量的值为0,不阻塞,立即返回,大于0可以加一

    参数:

    信号量的地址。

    返回值:

    成功:0

    失败:-1

3、信号量加一 V操作 sem_post()

  • 功能介绍

    #include <semaphore.h>
    int sem_post(sem_t *sem);
    

    函数功能:

    将信号量加一

    参数:

    信号量的地址

    返回值:

    成功:0

    失败:-1

4、销毁信号量

  • 功能介绍

    #include <semaphore.h>
    int sem_destroy(sem_t *sem);
    

    函数功能:

    销毁信号量

    参数:

    信号量的地址

    返回值:

    成功:0

    失败:-1

知识点3【信号量用于线程的互斥】

代码步骤

1、创建 初始化 阻塞回收线程 3个

2、线程函数创建void *名(void *arg)

封装一个函数my_printf()

这里用的函数实现的功能都是一样的,可以用同一个函数,但是为了提高观看的直观性,我们分成了3个进程函数

在这里我们运行一下验证函数功能

3、全局创建,初始化,销毁信号量 1个

4、在线程函数中执行PV操作

代码演示

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>//封装my_printf() 函数
void my_printf(char *);
//线程函数声明
void *my_fun01(void *arg);
void *my_fun02(void *arg);
void *my_fun03(void *arg);//全局创建信号量
sem_t sem;int main(int argc, char const *argv[])
{srand(time(NULL));//创建线程 3 个pthread_t tid1,tid2,tid3;//信号量初始化sem_init(&sem,0,1);//初始化信号地址,线程信号量,初始化值1//初始化线程pthread_create(&tid1,NULL,my_fun01,(void *)"pthread A  ");pthread_create(&tid2,NULL,my_fun02,(void *)"pthread B  ");pthread_create(&tid3,NULL,my_fun03,(void *)"pthread C  ");//销毁线程pthread_join(tid1,NULL);pthread_join(tid2,NULL);pthread_join(tid3,NULL);//摧毁信号量sem_destroy(&sem);return 0;
}
//my_printf() 函数实现
void my_printf(char *arr)
{while(*arr != 0){printf("%c",*arr);fflush(stdout);usleep(1000 * 100);arr++;}
}
//线程函数实现
void *my_fun01(void *arg)
{while(1){   //p操作sem_wait(&sem);//函数体my_printf((char *)arg);//v操作sem_post(&sem);//关索后休眠,防止重复抢锁//重要!!!!!usleep(1000 * 1000 *(rand()%4 + 1));}return NULL;
}
void *my_fun02(void *arg)
{while(1){   //p操作sem_wait(&sem);//函数体my_printf((char *)arg);//v操作sem_post(&sem);//关索后休眠,防止重复抢锁usleep(1000 * 100 *(rand()%4 + 1));}return NULL;
}
void *my_fun03(void *arg)
{while(1){   //p操作sem_wait(&sem);//函数体my_printf((char *)arg);//v操作sem_post(&sem);//关索后休眠,防止重复抢锁usleep(1000 * 100 *(rand()%4 + 1));}return NULL;
}

代码运行结果

这个是执行完1,2步骤后函数功能验证运行结果:

完整代码的运行结

知识点4【信号量用于线程的同步】

同步操作我们只需要改一下上述代码 但是为了让大家更好地理解 我将扔把全部代码发出

执行顺序:进程A,C,B

这里我先标出不同点地方:

1、信号量的个数

2、信号量的初始化和销毁

3、线程函数中PV原语步骤

整体代码演示:

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>//封装my_printf() 函数
void my_printf(char *);
//线程函数声明
void *my_fun01(void *arg);
void *my_fun02(void *arg);
void *my_fun03(void *arg);//全局创建信号量 同步 三个进程创建三个信号量
sem_t sem1,sem2,sem3;int main(int argc, char const *argv[])
{srand(time(NULL));//创建线程 3 个pthread_t tid1,tid2,tid3;//信号量初始化sem_init(&sem1,0,1);//初始化信号地址,线程信号量,初始化值1sem_init(&sem2,0,0);//初始化信号地址,线程信号量,初始化值0sem_init(&sem3,0,0);//初始化信号地址,线程信号量,初始化值0//初始化线程pthread_create(&tid1,NULL,my_fun01,(void *)"pthread A  ");pthread_create(&tid2,NULL,my_fun02,(void *)"pthread B  ");pthread_create(&tid3,NULL,my_fun03,(void *)"pthread C  ");//销毁线程pthread_join(tid1,NULL);pthread_join(tid2,NULL);pthread_join(tid3,NULL);//摧毁信号量sem_destroy(&sem1);sem_destroy(&sem2);sem_destroy(&sem3);return 0;
}
//my_printf() 函数实现
void my_printf(char *arr)
{while(*arr != 0){printf("%c",*arr);fflush(stdout);usleep(1000 * 100);arr++;}
}
//线程函数实现
void *my_fun01(void *arg)
{while(1){   //p操作sem_wait(&sem1);//函数体my_printf((char *)arg);//v操作sem_post(&sem3);//关索后休眠,防止重复抢锁//重要!!!!!usleep(1000 * 1000 *(rand()%2 + 1));}return NULL;
}
void *my_fun02(void *arg)
{while(1){   //p操作sem_wait(&sem2);//函数体my_printf((char *)arg);//v操作sem_post(&sem1);//关索后休眠,防止重复抢锁usleep(1000 * 100 *(rand()%4 + 1));}return NULL;
}
void *my_fun03(void *arg)
{while(1){   //p操作sem_wait(&sem3);//函数体my_printf((char *)arg);//v操作sem_post(&sem2);//关索后休眠,防止重复抢锁usleep(1000 * 100 *(rand()%4 + 1));}return NULL;
}

代码运行结果:

知识点5【无名信号量 用于 有血缘关系的进程间互斥】

互斥仍只需要一个信号量

有血缘关系的进程 说明 需要fork 创建子进程

现在只有一个问题 无名信号量是什么?

现在我们想一下 如果子进程1中,我们对一个变量的值进行修改,子进程2 中的值会改变吗?

答案是不会的,那我们该如何实现互斥和同步呢?

这里只需要找到子进程间能够互相识别的部分即可。这里利用我们 之前讲的进程间的共享内存中的磁盘映射mmap。

好了,现在思路有了 我们来写一下代码实现的步骤

代码实现步骤

1、进程的创建 父进程负责管理子进程的空间,子进程负责操作

2、父进程进行信号量磁盘映射,这里我们使用匿名映射

创建子进程,会不会重复映射呢?这个大家放心是不会的,因为系统会识别,父进程映射成功,子进程映射会失败的

3、进程中先实现功能基本输出,并进行验证

4、验证后再完成互斥操作

代码实现

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>#define NUM 2
//打包my_printf函数
void my_printf(char *arr);
int main(int argc, char const *argv[])
{//创建一个数组用来存储 子进程的id 在本项目中不需要 目的是帮助大家回忆pid_t arr[NUM] = {0};//映射mmap信号量sem_t *sem = (sem_t *)mmap(NULL,sizeof(sem_t),PROT_WRITE|PROT_READ,MAP_SHARED | MAP_ANONYMOUS,-1,0);//信号量的初始化sem_init(sem,1,1);//父进程创建两个子进程int i = 0;for (;i < NUM; i++){arr[i] = fork();if(arr[i] == -1){perror("fork");_exit(-1);}else if(arr[i] == 0){break;}}//子进程1 打印worldif(i == 0){//P操作sem_wait(sem);//函数体my_printf("world");//V操作sem_post(sem);_exit(-1);}//子进程2 打印helloelse if(i == 1){//P操作sem_wait(sem);//函数体my_printf("hello");//V操作sem_post(sem);_exit(-1);}//父进程 回收空间waitpidwhile(1){int ret = waitpid(-1,NULL,WNOHANG);if(ret < 0){break;}}//销毁信号量sem_destroy(sem);return 0;
}
void my_printf(char *arr)
{while(*arr != 0){printf("%c",*arr);fflush(stdout);usleep(1000 * 200);//0.2s打印一次arr++;}return;
}

这里我们补充一个小点:

MAP_ANONYMOUS是匿名的意思,如果用了这个在文件描述符必须写-1

代码运行结果

1、没有实现互斥的情况

2、实现互斥的情况

知识点5【无名信号量 用于 有血缘关系的进程间同步】

代码演示

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>#define NUM 2
//打包my_printf函数
void my_printf(char *arr);
int main(int argc, char const *argv[])
{//创建一个数组用来存储 子进程的id 在本项目中不需要 目的是帮助大家回忆pid_t arr[NUM] = {0};//映射mmap信号量 由于有两个子进程,并且要完成同步操作,因此我们需要完成两次映射磁盘sem_t *sem1 = (sem_t *)mmap(NULL,sizeof(sem_t),PROT_WRITE|PROT_READ,MAP_SHARED | MAP_ANONYMOUS,-1,0);sem_t *sem2 = (sem_t *)mmap(NULL,sizeof(sem_t),PROT_WRITE|PROT_READ,MAP_SHARED | MAP_ANONYMOUS,-1,0);//我们这里实现先遍历 world 再遍历 hello//信号量的初始化sem_init(sem1,1,1);sem_init(sem2,1,0);//父进程创建两个子进程int i = 0;for (;i < NUM; i++){arr[i] = fork();if(arr[i] == -1){perror("fork");_exit(-1);}else if(arr[i] == 0){break;}}//子进程1 打印worldif(i == 0){//P操作sem_wait(sem1);//函数体my_printf("world");//V操作sem_post(sem2);_exit(-1);}//子进程2 打印helloelse if(i == 1){//P操作sem_wait(sem2);//函数体my_printf("hello");//V操作sem_post(sem1);_exit(-1);}//父进程 回收空间waitpidwhile(1){int ret = waitpid(-1,NULL,WNOHANG);if(ret < 0){break;}}//销毁信号量sem_destroy(sem1);sem_destroy(sem2);return 0;
}
void my_printf(char *arr)
{while(*arr != 0){printf("%c",*arr);fflush(stdout);usleep(1000 * 200);//0.2s打印一次arr++;}return;
}

代码运行结果

下面将标出不同的地方:

代码中遇到的问题:

1、子进程的创建步骤 有些模糊

逻辑,循环中,应是只有子进程才会break,父进程要一直运行循环,不能是因为是break退出。

2、造成了死锁

结束

代码重在练习!

代码重在练习!

代码重在练习!

今天的分享就到此结束了,希望对你有所帮助,如果你喜欢我的分享,请点赞收藏夹关注,谢谢大家!!!

今天的内容,中有遗漏了信号量用于无血缘关系的进程的互斥与同步

是因为我在写的过程中遇到了一些问题,我解决后将进行补充。

http://www.dtcms.com/wzjs/183075.html

相关文章:

  • 国内最大的开源网站工具站seo
  • 购物网站一般分几大模块百度注册
  • 做自媒体的网站湖南seo排名
  • 日本优秀设计网站网络营销知名企业
  • b2b网站大全网址大全域名ip查询
  • 购物网站建设教程18款禁用软件黄app免费
  • 手机网站建设电话seo的作用主要有
  • 淘宝网站首页设计分析百度官方网站下载
  • 深圳城乡和住房建设局网站课程培训
  • 河北做it的网站360推广平台登录入口
  • 如何建立自己的网站步骤网络服务包括哪些内容
  • 设计大型网站建设市场调研分析
  • 互联免费虚拟主机sem优化师是做什么的
  • 常见的网站推广途径深圳网络优化seo
  • 深圳百度推广网站建设合肥seo排名优化
  • 想学网站建设与设计的书籍国内最大的搜索引擎
  • 网站做wanzhihou百度一下你就知道了主页
  • 岳阳网站建设有哪些营业推广是什么意思
  • 学做网站论坛会员账号做网站公司
  • 请人做网站 出现纠纷怎么办百度百家号注册
  • 仿木鱼网络网站在线磁力搜索引擎
  • 做测试的网站有哪些合作seo公司
  • 如何做经营性网站备案如何制作一个网页
  • 金湖县住房和城乡建设局网站网络工程师
  • 建设银行信用卡积分兑换商城网站新网站排名优化怎么做
  • dtcms怎么做自己网站竞价排名的弊端
  • 高德北斗导航网站站长seo推广
  • 北京东站英文seo推广
  • 免费下载ps素材网站品牌企业seo咨询
  • 武汉中建广场做网站的公司有哪些惠州网站排名提升