Linux多进程多线程例子

看了apue3,关于进程线程和进程间通信写了一个例子,方便自己理解相关知识,备忘。

  1 #include <stdlib.h>
  2 #include <stdio.h>
  3 #include <unistd.h>
  4 #include <pthread.h>
  5 #include <sys/types.h>
  6 #include <sys/ipc.h>
  7 #include <sys/shm.h>
  8 #include <sys/sem.h>
  9
 10 //这里全局变量简化线程代码量而已,实际应该在线程获取这些变量再操作。
 11 long *shmaddr;
 12 int semid;
 13
 14 /**
 15  * 互斥量加或减
 16  * @param  semid 互斥量id
 17  * @param  pv    整数加,负数减
 18  */
 19 void sem_pv(int semid, short pv)
 20 {
 21     struct sembuf buf = {0, 0, 0};
 22     buf.sem_op = pv;
 23     buf.sem_num = 0;
 24     semop(semid, &buf, 1);
 25 }
 26
 27 void thread1(void *arg)
 28 {
 29     srand((long)arg + time(0));    //(时间 + 索引号)生成随机种子
 30     while (1) {
 31         sleep(rand() % 8 + 1);    //睡眠1~8s
 32         sem_pv(semid, -1);    //sem - 1,若sem = 1,不阻塞,若sem = 0,阻塞
 33         *shmaddr += 1;    //共享值 += 线程号
 34         printf("This is 1 thread, *shmaddr = %ld!!\n", *shmaddr);
 35         sem_pv(semid, +1);    //sem + 1,唤醒其他已经阻塞的线程
 36     }
 37     pthread_exit((arg));
 38 }
 39
 40 void thread2(void *arg)
 41 {
 42     srand((long)arg + time(0));
 43     while (1) {
 44         sleep(rand() % 8 + 1);
 45         sem_pv(semid, -1);
 46         *shmaddr += 2;
 47         printf("This is 2 thread, *shmaddr = %ld!!\n", *shmaddr);
 48         sem_pv(semid, +1);
 49     }
 50     pthread_exit(arg);
 51 }
 52
 53 void thread3(void *arg)
 54 {
 55     srand((long)arg + time(0));
 56     while (1) {
 57         sleep(rand() % 8 + 1);
 58         sem_pv(semid, -1);
 59         *shmaddr += 3;
 60         printf("This is 3 thread, *shmaddr = %ld!!\n", *shmaddr);
 61         sem_pv(semid, +1);
 62     }
 63     pthread_exit(arg);
 64 }
 65
 66 void thread4(void *arg)
 67 {
 68     srand((long)arg + time(0));
 69     while (1) {
 70         sleep(rand() % 8 + 1);
 71         sem_pv(semid, -1);
 72         *shmaddr += 4;
 73         printf("This is 4 thread, *shmaddr = %ld!!\n", *shmaddr);
 74         sem_pv(semid, +1);
 75     }
 76     pthread_exit(arg);
 77 }
 78
 79 void thread5(void *arg)
 80 {
 81     srand((long)arg + time(0));
 82     while (1) {
 83         sleep(rand() % 8 + 1);
 84         sem_pv(semid, -1);
 85         *shmaddr += 5;
 86         printf("This is 5 thread, *shmaddr = %ld!!\n", *shmaddr);
 87         sem_pv(semid, +1);
 88     }
 89     pthread_exit(arg);
 90 }
 91
 92 void thread6(void *arg)
 93 {
 94     srand((long)arg + time(0));
 95     while (1) {
 96         sleep(rand() % 8 + 1);
 97         sem_pv(semid, -1);
 98         *shmaddr += 6;
 99         printf("This is 6 thread, *shmaddr = %ld!!\n", *shmaddr);
100         sem_pv(semid, +1);
101     }
102     pthread_exit(arg);
103 }
104
105 void thread7(void *arg)
106 {
107     srand((long)arg + time(0));
108     while (1) {
109         sleep(rand() % 8 + 1);
110         sem_pv(semid, -1);
111         *shmaddr += 7;
112         printf("This is 7 thread, *shmaddr = %ld!!\n", *shmaddr);
113         sem_pv(semid, +1);
114     }
115     pthread_exit(arg);
116 }
117
118 void thread8(void *arg)
119 {
120     srand((long)arg + time(0));
121     while (1) {
122         sleep(rand() % 8 + 1);
123         sem_pv(semid, -1);
124         *shmaddr += 8;
125         printf("This is 8 thread, *shmaddr = %ld!!\n", *shmaddr);
126         sem_pv(semid, +1);
127     }
128     pthread_exit(arg);
129 }
130
131 typedef void (*thread)(void *arg);
132 #define PROJ_ID 8
133 int main(int argc, char const *argv[])
134 {
135     pid_t pid[4];
136     pthread_t thid[8];
137     thread fun[8] = {thread1, thread2, thread3, thread4, thread5, thread6, thread7, thread8};
138     key_t key;
139     int shmid;
140     int i;
141     long index;    //这里使用long是(void *)<---->long,long和指针占用内存大小(主机64bit)一样,否则gcc会报warnning
142     union semun {
143         int            val;
144         struct semid_ds        *buf;
145         unsigned short        *array;
146     } semopts;
147
148     if ((key = ftok("." , PROJ_ID )) == -1) {
149         perror("ftok error");
150         exit(1);
151     }
152     if ((shmid = shmget(key, sizeof(long), IPC_CREAT | 0666)) == -1) {
153         perror("shmget error");
154         exit(1);
155     }
156     if ((shmaddr = (long *)shmat(shmid, NULL, 0)) == (long *) - 1) {
157         perror("shmat error");
158         exit(1);
159     }
160     *shmaddr = 0;    //初始化共享量
161
162     if ((semid = semget(key, 1, IPC_CREAT | 0666)) == -1) {
163         perror("semget failed");
164         exit(1);
165     }
166     semopts.val = 1;    //信号量初始为1
167
168     if (semctl(semid, 0, SETVAL, semopts) == -1) {
169         perror("semctl failed");
170         exit(1);
171     }
172     //创建4进程 & 8线程
173     for (i = 0; i < 4; ++i) {
174         pid[i] = fork();
175         if (pid[i] == 0) {
176             index = 2 * i;
177             if (pthread_create(&thid[index], NULL, (void *)fun[index], (void *)index) != 0) {
178                 perror("thread error");
179                 exit(1);
180             }
181             index++;
182             if (pthread_create(&thid[index], NULL, (void *)fun[index], (void *)index) != 0) {
183                 perror("thread error");
184                 exit(1);
185             }
186             sleep(1);
187             printf("This is %d process\n", i);
188             printf("Children‘s pid = %d, ppid = %d\n", getpid(), getppid());
189             while (1)
190                 sleep(10);
191             exit(0);
192
193         } else if (pid[i] < 0) {
194             perror("fork error");
195             exit(1);
196         }
197     }
198     //父进程退出,4个子进程成为孤儿进程
199     exit(0);
200 }

程序开启4进程8线程同时一起累加。线程可以用全局变量同步,但4个子进程间不能共享累加结果,需要用进程共享量。同时涉及到多线程多进程的并发,需要用进程互斥量。

时间: 2024-10-10 23:30:24

Linux多进程多线程例子的相关文章

Linux 多进程多线程相关概念

进程:可执行程序是存储在磁盘设备上的由代码和数据按某种格式组织的静态实体,而进程是可被调度的代码的动态运行.在Linux系统中,每个进程都有各自的生命周期.在一个进程的生命周期中,都有各自的运行环境以及所需的资源,这些信息都记录在各自的进程控制块中,以便系统对这些进程进行有效的管理,进程控制块的结构如下图所示: 每个进程都有各自独立的虚拟地址空间,空间的大小与所基于的硬件体系结构有关.虚拟空间中各区代表的意义,代码段存储指令序列和只读数据,多个进程实例可共享代码段.数据段用来存放全局变量和静态变

Linux多进程之间的文件锁

之前对于文件的操作通常在一个进程中完成,最近需要在两个进程中对同一个文件进行操作.故想到了文件锁. Linux下可以使用flock()函数对文件进行加锁解锁等操作.简单介绍下flock()函数: 表头文件  #include 定义函数  int flock(int fd,int operation); 函数说明  flock()会依参数operation所指定的方式对参数fd所指的文件做各种锁定或解除锁定的动作.此函数只能锁定整个文件,无法锁定文件的某一区域. 参数  operation有下列四

[转帖]Windows和Linux对决(多进程多线程)

Windows和Linux对决(多进程多线程) https://blog.csdn.net/world_2015/article/details/44920467 太长了 还没看完.. 还是没太理解好呢.. 关于 windows 和 linux的东西 先放这里 晚上有时间仔细啃一下. 并行程序设计分为共享内存和消息驱动(其实就是分布式内存)两种, 共享内存:所有CPU共内存,所有CPU由一个操作系统控制的,例如Windows和Linux/UNIX,目前流行的多核.多CPU机器都是属于这种: 消息

Linux统系统开发11 Socket API编程2 多进程 多线程 高并发处理

[本文谢绝转载原文来自http://990487026.blog.51cto.com] <纲要> Linux统系统开发11 Socket API编程2 多进程 多线程 高并发处理 UDP服务器 客户端最小模型,处理字符转大写 TCP 多进程并发服务器模型,为每个客户端开启一个进程: TCP 多线程服务器模型,使用wrap函数封装 作业: ---------------------------------------------------- UDP服务器 客户端最小模型,处理字符转大写 [em

[转]一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程

一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程 希望此文能给初学多线程编程的朋友带来帮助,也希望牛人多多指出错误. 另外感谢以下链接的作者给予,给我的学习带来了很大帮助 http://blog.csdn.net/locape/article/details/6040383 http://www.cnblogs.com/liuweijian/archive/2009/12/30/1635888.html 一.什么是多线程? 当我自己提出这个问题的时候,我还是很老实的拿着操作系

一个简单的多进程+多线程+协程的例子

因为一个朋友最近想搞接口压力测试,推荐了jmeter,因为jmeter开源,且有命令行启动模式,方便封装.兴起时,自己也简单实现了一下高并发的脚本. 采用的是多进程+多线程+协程.想法是这样的,多进程是为了有效利用多核,理论上最好一个核对应一个进程比较好:那我为什么还要用多线程呢?不怕GIL全局锁吗?这是因为我用了gevent处理,请求采用requests,但requests是阻塞的方法,所以我把requests操作丢到协程做,就没啥问题了.接下来看看脚本,实现了一个2000并发量的脚本(写的比

转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)

Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥) 介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可以看作是Unix进程的表亲,同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等.但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage). 一

linux下多线程编程

最近研究mysql源码,各种锁,各种互斥,好在我去年认真学了<unix环境高级编程>, 虽然已经忘得差不多了,但是学过始终是学过,拿起来也快.写这篇文章的目的就是总结linux 下多线程编程,作为日后的参考资料. 本文将介绍linux系统下多线程编程中,线程同步的各种方法.包括: 互斥量(mutex) 读写锁 条件变量 信号量 文件互斥 在介绍不同的线程同步的方法之前,先简单的介绍一下进程和线程的概念, 它们的优缺点,线程相关的API,读者——写者问题和哲学家就餐问题. 基础知识 1. 进程和

Linux 多进程学习

1Linux进程概述 进程是一个程序执行一次的过程,他和程序有着本质的区别.程序是静态的,他是一些保存在磁盘上的指令有序的集合. 进程是动态的概念,他是运行者的程序,包含进程的动态创建,调度和消亡,是Linux的基本调度单位. 进程控制块(PCB)是进程的静态描述,包括进程的描述信息,进程的控制信息,以及资源信息 时间片:他轮流在每个进程的得到的时间片用完后从进程那里千回控制权 1.1进程标识 os会为每一个进程分配一个唯一的盛行ID,作为进程的标识号(pid),还有父进程ID(ppid) 所有