• 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

    在这里插入图片描述

  • 相关阅读:
    ssh登录界面变成vim提示,进不去系统
    前端研习录(11)——CSS3新特性——圆角及阴影讲解及示例说明
    MySQL 8.2 – 透明的读写分离(译)
    九、(正点原子)Linux定时器
    [数据可视化] 图表设计原则
    深入理解高级数据结构之B+树
    11g ADG级联备库基础测试环境准备
    winform入门篇 第13章 菜单栏
    Elasticsearch 开放 inference API 增加了对 OpenAI chat completions 的支持
    跨进程启动后台服务
  • 原文地址:https://blog.csdn.net/qq_33808440/article/details/126928591