• c语言系统编程十四:Linux进程间的同步与互斥


    一 无名信号量用于有血缘关系的进程间的互斥

    #include
    #include
    #include
    #include
    #include
    #include
    #include 
    
    void my_printf(void *arg)
    {
    	char *str = (char *)arg;
    	while(1)
    	{
    		int n = 0;
    		while(*(str+n) != '\0')
    		{
    			printf("%c", *(str+n));
    			fflush(stdout);
    			n++;
    			sleep(1);
    		}
    	}
    	return ;
    }
    
    
    int main(void)
    {
    	//定义一个无名信号量
    	//MAP_ANONYMOUS是匿名映射;-1是不需要文件描述符
    	sem_t * sem = mmap(NULL, sizeof(sem_t), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
    	//初始化无名信号量sem。第一个1表示进程间的,第二个1表示初始化为1
    	sem_init(sem, 1,1);
    	//创建子进程
    	pid_t  pid;
    	pid = fork();
    	if(pid == 0)  //子进程
    	{
    		sem_wait(sem);
    		my_printf("123456");
    		sem_post(sem);
    		return 0;
    	}
    	//主进程
    	sem_wait(sem);
    	my_printf("abcdef");
    	sem_post(sem);
    	//销毁信号量
    	sem_destroy(sem);
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    二 无名信号量用于有血缘关系的进程间的同步

    #include
    #include
    #include
    #include
    #include
    #include
    #include 
    
    void my_printf(void *arg)
    {
    	char *str = (char *)arg;
    	int n = 0;
    	while(*(str+n) != '\0')
    	{
    		printf("%c", *(str+n));
    		fflush(stdout);
    		n++;
    		sleep(1);
    	}
    	return ;
    }
    
    
    int main(void)
    {
    	//定义两个无名信号量
    	//MAP_ANONYMOUS是匿名映射;-1是不需要文件描述符
    	sem_t * sem1 = mmap(NULL, sizeof(sem_t), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
    	sem_t * sem2 = mmap(NULL, sizeof(sem_t), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
    	//初始化无名信号量sem。第一个1表示进程间的,第二个1表示初始化为1
    	sem_init(sem1, 1,1);
    	sem_init(sem2, 1,0);
    	//创建子进程
    	pid_t  pid;
    	pid = fork();
    	if(pid == 0)  //子进程
    	{
    		sem_wait(sem1);
    		my_printf("123456");
    		sem_post(sem2);
    		return 0;
    	}
    	//主进程
    	sem_wait(sem2);
    	my_printf("abcdef");
    	sem_post(sem1);
    	//销毁信号量
    	sem_destroy(sem1);
    	sem_destroy(sem2);
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    三 有名信号量用于无血缘关系的进程间的互斥

    3.1 创建有名信号量函数sem_open

    1. 需要的头文件和函数原型:
    #include 
    #include 
    #include 
    
    //信号量存在
    sem_t * sem_open(const char *name, int oflag);
    //信号量不存在
    sem_t * sem_open(const char *name, int oflag, mode_t mode, unsigned int value);
    
    2. 功能:
    创建一个信号量
    
    3. 参数:
    	name:信号量的名字
    	oflag:sem_open函数的权限标志
    	mode:文件权限(可读,可写,可执行0777)的设置
    	value:信号量的初始值
    
    4. 返回值:
    	成功:信号量的地址
    	失败:SEM_FAILED
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    3.2 信号量的关闭函数sem_close

    int sem_close(sem_t *sem);
    功能:关闭信号量
    参数:信号量的地址
    返回值:成功0;失败-1
    
    • 1
    • 2
    • 3
    • 4

    3.3 信号量文件的删除函数sem_unlink

    int sem_unlink(const char *name);
    功能:删除信号量文件
    参数:信号量的文件名
    返回值:成功0;失败-1
    
    • 1
    • 2
    • 3
    • 4

    3.4 代码实现

    #include
    #include
    #include
    #include
    #include
    #include
    #include 
    #include 
    #include 
    
    void my_printf(void *arg)
    {
    	char *str = (char *)arg;
    	int n = 0;
    	while(*(str+n) != '\0')
    	{
    		printf("%c", *(str+n));
    		fflush(stdout);
    		n++;
    		sleep(1);
    	}
    	return ;
    }
    
    
    int main(void)
    {
    	//创建一个有名信号量sem_open, 最后一个参数是初始值
    	sem_t * sem = sem_open("sem", O_RDWR|O_CREAT, 0666, 1);
    	//P 操作
    	sem_wait(sem);
    	//执行任务
    	my_printf("123456\n");
    	//V 操作
    	sem_post(sem);
    	//关闭信号量
    	sem_close(sem);
    	//销毁信号量
    	sem_destroy(sem);
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    四 有名信号量用于无血缘关系的进程间的同步

    4.1 进程1的代码

    #include
    #include
    #include
    #include
    #include
    #include
    #include 
    #include 
    #include 
    
    void my_printf(void *arg)
    {
    	char *str = (char *)arg;
    	int n = 0;
    	while(*(str+n) != '\0')
    	{
    		printf("%c", *(str+n));
    		fflush(stdout);
    		n++;
    		sleep(1);
    	}
    	return ;
    }
    
    
    int main(void)
    {
    	//创建两个有名信号量sem_open, 最后一个参数是初始值
    	sem_t * sem1 = sem_open("sem1", O_RDWR|O_CREAT, 0666, 1);
    	sem_t * sem2 = sem_open("sem2", O_RDWR|O_CREAT, 0666, 0);
    	//P 操作
    	sem_wait(sem1);
    	//执行任务
    	my_printf("123456\n");
    	//V 操作
    	sem_post(sem2);
    	//关闭信号量
    	sem_close(sem1);
    	sem_close(sem2);
    	//销毁信号量
    	sem_destroy(sem1);
    	sem_destroy(sem2);
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    4.2 进程2的代码

    #include
    #include
    #include
    #include
    #include
    #include
    #include 
    #include 
    #include 
    
    void my_printf(void *arg)
    {
    	char *str = (char *)arg;
    	int n = 0;
    	while(*(str+n) != '\0')
    	{
    		printf("%c", *(str+n));
    		fflush(stdout);
    		n++;
    		sleep(1);
    	}
    	return ;
    }
    
    
    int main(void)
    {
    	//创建两个有名信号量sem_open, 最后一个参数是初始值
    	sem_t * sem1 = sem_open("sem1", O_RDWR|O_CREAT, 0666, 1);
    	sem_t * sem2 = sem_open("sem2", O_RDWR|O_CREAT, 0666, 0);
    	//P 操作
    	sem_wait(sem2);
    	//执行任务
    	my_printf("abcdef\n");
    	//V 操作
    	sem_post(sem1);
    	//关闭信号量
    	sem_close(sem1);
    	sem_close(sem2);
    	//销毁信号量
    	sem_destroy(sem1);
    	sem_destroy(sem2);
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    在这里插入图片描述

  • 相关阅读:
    Java题目集
    抖音热搜查询易语言代码
    高考学计算机专业的小白指南,一些比较实用的软件,快速入手计算机
    【Java并发编程 】同步——volatile 关键字
    K8S hostpath配置
    Spring Boot多数据源配置并通过注解实现动态切换数据源
    代码随想录算法训练营第六十二天 | 84.柱状图中最大的矩形
    Web安全常见攻击
    STP生成树协议详解
    振南技术干货集:振南当年入门C语言和单片机的那些事儿(1)
  • 原文地址:https://blog.csdn.net/qq_33808440/article/details/126928591