Linux多线程编程
-
使用线程的目的就是要合理的利用资源,提高cpu的效率。
-
进程:一个正在运行的程序,资源分配的最小单位。
-
线程:cpu调度的基本单位。
-
并发:同一个时间段内,不同的事情交替的进行操作。(单核的,假象)
-
并行:同一个时刻内,不同的事情做多个事情进行操作。(多核的)
-
同步:彼此有依赖关系的调用不应该同事发生,同步就是要阻止那些"同时发生"的事情。
-
异步:任何两个彼此独立的操作是异步的,它表明事情的独立发生。
include<pthread.h>
编译时要用到pthread 库:gcc -lpthread
//pthreadid.c
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
int main()
{
//pid_t 和pthread_t 都是unsigned long int 类型,
//其他的FreeBSD,MacOS 中pthread_t不是此类型。
pid_t pid;
pthread_t tid;
pid = getpid();
tid = pthread_self();
printf("pid is %u,tid is %lu",pid,tid);
return 0;
}
360截图20200410173416453.jpg
错误码位置:/usr/include/asm-generic/errno.h
360截图20200410173956523.jpg//pthread_create.c
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
void print_id(char *s)
{
pid_t pid;
pthread_t tid;
pid = getpid();
tid = pthread_self();
printf("%s pid is %u,tid is 0x%lx\n",s,pid,tid);
}
void *thread_fun(void *arg)
{
print_id(arg);
return (void*)0;
}
int main()
{
pthread_t ntid;
int err;
err = pthread_create(&ntid,NULL,thread_fun,"new thread");
if(err != 0)
{
printf("create new thread failed\n");
return 0;
}
print_id("main thread:");
sleep(2);
return 0;
}
gcc pthread_create.c -lpthread
-
主线程利用pthread_exit退出,其他线程不会退出。
-
如果return main函数返回,则其他线程也就退出了。
//main_thread.c
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
struct student{
int age;
char name[20];
char id[4];
};
void *thread_fun(void *stu)
{
printf("student age is %d,name is %s,id is %s\n",((struct student*)stu)->age,((struct student*)stu)->name,((struct student*)stu)->id);
}
int main(int argc,char* argv[])
{
pthread_t ntid;
int err;
int *rval;
struct student stu;
stu.age = 20;
memcpy(stu.name,"zhangsan",20);
memcpy(stu.id,"0083",5);
err = pthread_create(&ntid,NULL,thread_fun,(void*)(&stu));
if(err != 0)
{
printf("create new thread failed\n");
return 0;
}
int i;
printf("main thread have %d args\n",argc);
for(i = 0;i < argc;i++)
{
printf("main thread argv is %s\n",argv[i]);
}
//sleep(1);
pthread_exit(rval);
return 0;
}
思考:主子线程交替打印奇数偶数。
-
线程的几种状态:就绪,运行,阻塞,终止
image.png
-
如果进程中的任意一个线程调用了exit,_Exit, _exit,那么整个进程就终止。
-
不终止进程的线程终止方式:
-
从启动例程中返回,返回值是线程的退出码
-
线程可以被同一个进程中的其他线程取消
-
线程调用pthread_exit(void *rval)函数,rval是退出码
-
- 360截图20200410184643250.jpg
//thread_exit.c
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
//验证调用exit ,return ,pthread_exit 函数是否会引起主进程的退出。
void *thread_fun(void *arg)
{
if(strcmp("1",(char*)arg) == 0)
{
printf("new thread return !\n");
return (void*)1;
}
if(strcmp("2",(char*)arg) == 0)
{
printf("new thread pthread_exit !\n");
pthread_exit((void*)2);
}
if(strcmp("3",(char*)arg) == 0)
{
printf("new thread exit !\n");
exit(3);
}
}
int main(int argc,char *argv[])
{
pthread_t tid;
int err;
err = pthread_create(&tid,NULL,thread_fun,(void*)argv[1]);
if(err != 0)
{
printf("creae new thread failed\n");
return 0;
}
sleep(1);
printf("main thread\n");
return 0;
}
- 思考:创建多个线程,证明任意一个线程调用exit函数都会导致进程的退出。
360截图20200410200000300.jpg
//thread_join.c
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
void *thread_fun(void* arg)
{
printf("wo shi thread1 \n");
return (void*)1;
}
void* thread_fun2(void* arg)
{
printf("wo shi thread2 \n");
pthread_detach(pthread_self());
pthread_exit((void*)2);
}
int main()
{
int err1,err2;
pthread_t tid1,tid2;
void *rval1,*rval2;
err1 = pthread_create(&tid1,NULL,thread_fun,NULL);
err2 = pthread_create(&tid2,NULL,thread_fun2,NULL);
if(err1 || err2)
{
printf("create new thread failed\n");
return 0;
}
printf("main thread\n");
printf("join1 rval is %d\n",pthread_join(tid1,&rval1));
printf("join2 rval is %d\n",pthread_join(tid2,&rval2));
printf("thread 1 exit code is %d\n",(int*)rval1);
printf("thread 2 exit code is %d\n",(int*)rval2);
printf("wo shi main thread\n");
return 0;
}
- 思考:证明当pthread_join()返回以后,其他线程不能调用pthread_join连接id指定的线程
360截图20200410202635779.jpg
360截图20200410202715267.jpg
360截图20200410202825659.jpg
360截图20200410202905481.jpg
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
void *thread_fun(void* arg)
{
int stateval;
stateval = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
if(stateval != 0)
{
printf("set cancel state failed\n");
}
printf("Im new thread\n");
sleep(4);
printf("about to cancel\n");
stateval = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
//stateval = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
if(stateval != 0)
{
printf("set cancel state failed\n");
}
int typeval = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
if(typeval != 0)
{
printf("set cancel type failed\n");
}
printf("first cancel point\n");
printf("second cancel point\n");
return (void*)20;
}
int main()
{
pthread_t tid;
int err,cval,jval;
void *rval;
err = pthread_create(&tid,NULL,thread_fun,NULL);
if(err != 0)
{
printf("create thread failed\n");
return 0;
}
sleep(2);
cval = pthread_cancel(tid);
if(cval != 0)
{
printf("cancel thread failed\n");
}
jval = pthread_join(tid,&rval);
printf("new thread exit code is %d\n",(int*)rval);
return 0;
}
![
360截图20200410202618650.jpg
思考:证明线程可以自己取消自己。
360截图20200410205105491.jpg//
#include<stdio.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
void *thread_fun(void *arg)
{
sleep(1);
printf("wo shi new thread\n");
return (void*)0;
}
int main()
{
pthread_t tid;
int err;
int s;
void *rval;
err = pthread_create(&tid,NULL,thread_fun,NULL);
if(err != 0)
{
printf("cancel new thread failed\n");
return 0;
}
sleep(1);
s = pthread_kill(tid,0);
//s = pthread_kill(tid,SIGQUIT);
if(s == ESRCH)
{
printf("thread tid is not found\n");
}
pthread_join(tid,&rval);
printf("wo shi main thread\n");
return 0;
}
360截图20200411081047852.jpg
360截图20200411081313301.jpg
360截图20200411081335207.jpg
360截图20200411081350134.jpg
//thread.kill.c
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
void sig_handler1(int arg)
{
printf("thread1 get signal\n");
return;
}
void sig_handler2(int arg)
{
printf("thread2 get signal\n");
return;
}
void *thread_func(void* arg)
{
printf("new thread 1\n");
struct sigaction act;
memset(&act,0,sizeof(act));
act.sa_handler = sig_handler1;
sigaction(SIGQUIT,&act,NULL);
pthread_sigmask(SIG_BLOCK,&act.sa_mask,NULL);
sleep(2);
}
void *thread_func2(void* arg)
{
printf("new thread 2\n");
struct sigaction act;
memset(&act,0,sizeof(act));
act.sa_handler = sig_handler2;
sigaction(SIGQUIT,&act,NULL);
//pthread_sigmask(SIG_BLOCK,&act.sa_mask,NULL);
sleep(2);
}
int main()
{
pthread_t tid1,tid2;
int err;
int s;
err = pthread_create(&tid1,NULL,thread_fun,NULL);
if(err != 0)
{
printf("create new thread 1 failed\n");
return ;
}
err = pthread_create(&tid2,NULL,thread_fun2,NULL);
if(err != 0)
{
printf("create new thread 2 failed\n");
return ;
}
sleep(1);
s = pthread_kill(tid1,SIGQUIT);
if(s != 0)
{
printf("send signal to thread1 failed\n");
}
s = pthread_kill(tid2,SIGQUIT);
if(s != 0)
{
printf("send signal to thread2 failed\n");
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return 0;
}
思考:证明SIGKILL和SIGSTOP 是无法阻塞的。
360截图20200411082537583.jpg
360截图20200411082703520.jpg
//thread_clean.c
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
void *first_clean(void* arg)
{
printf("%s first clean\n",arg);
return (void*)0;
}
void *second_clean(void* arg)
{
printf("%s second clean\n",arg);
return (void*)0;
}
void *thread_fun1(void *arg)
{
printf("new thread1 \n");
pthread_cleanup_push(first_clean,"thread1");
pthread_cleanup_push(second_clean,"thread1");
pthread_cleanup_pop(1);
pthread_cleanup_pop(0);
return (void*)1;
}
void *thread_fun2(void *arg)
{
printf("new thread2 \n");
pthread_cleanup_push(first_clean,"thread2");
pthread_cleanup_push(second_clean,"thread2");
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
pthread_exit((void*)2);
}
int main()
{
pthread_t tid1,tid2;
int err;
err = pthread_create(&tid1,NULL,thread_fun1,NULL);
if(err != 0)
{
printf("create new thread1 failed\n");
return;
}
err = pthread_create(&tid1,NULL,thread_fun2,NULL);
if(err != 0)
{
printf("create new thread2 failed\n");
return;
}
sleep(2);
return 0;
}
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
struct student{
int id;
int age;
int name;
}stu;
int i;
void *thread_fun1(void *arg)
{
while(1)
{
stu.id = i;
stu.age = i;
stu.name = i;
i++;
if(stu.id != stu.age || stu.id != stu.name || stu.age != stu.name)
{
printf("%d,%d,%d\n",stu.id,stu.age,stu.name);
break;
}
}
return (void*)0;
}
void *thread_fun2(void *arg)
{
while(1)
{
stu.id = i;
stu.age = i;
stu.name = i;
i++;
if(stu.id != stu.age || stu.id != stu.name || stu.age != stu.name)
{
printf("%d,%d,%d\n",stu.id,stu.age,stu.name);
break;
}
}
return (void*)0;
}
int main()
{
pthread_t tid1,tid2;
int err;
err = pthread_create(&tid1,NULL,thread_fun1,NULL);
if(err != 0)
{
printf("create new thread1 failed\n");
return;
}
err = pthread_create(&tid2,NULL,thread_fun2,NULL);
if(err != 0)
{
printf("create new thread 2failed\n");
return;
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return 0;
}
360截图20200411082736580.jpg
360截图20200411084557401.jpg
/usr/include/bits/pthreadtypes.h中查看pthread_mutex_t
360截图20200411085525294.jpg#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
struct student{
int id;
int age;
int name;
}stu;
int i;
pthread_mutex_t mutex;
void* thread_fun1(void *arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
stu.id = i;
stu.age = i;
stu.name = i;
i++;
if(stu.id != stu.age || stu.id != stu.name || stu.age != stu.name)
{
printf("%d,%d,%d\n",stu.id,stu.age,stu.name);
break;
}
pthread_mutex_unlock(&mutex);
}
return (void*)0;
}
void* thread_fun2(void *arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
stu.id = i;
stu.age = i;
stu.name = i;
i++;
if(stu.id != stu.age || stu.id != stu.name || stu.age != stu.name)
{
printf("%d,%d,%d\n",stu.id,stu.age,stu.name);
break;
}
pthread_mutex_unlock(&mutex);
}
return (void*)0;
}
int main()
{
pthread_t tid1,tid2;
int err;
err = pthread_mutex_init(&mutex,NULL);
if(err != 0)
{
printf("init mutext failed\n");
return;
}
err = pthread_create(&tid1,NULL,thread_fun1,NULL);
if(err != 0)
{
printf("create new thread1 failed\n");
return;
}
err = pthread_create(&tid2,NULL,thread_fun2,NULL);
if(err != 0)
{
printf("create new thread 2failed\n");
return;
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return 0;
}
360截图20200411090332958.jpg
360截图20200411090556086.jpg
360截图20200411090624470.jpg
360截图20200411091028102.jpg
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int num = 0;
pthread_rwlock_t rwlock;
void* thread_fun1(void *arg)
{
int err;
pthread_rwlock_rdlock(&rwlock);
//pthread_rwlock_wrlock(&rwlock);
printf("thread 1 print num %d\n",num);
sleep(5);
printf("thread 1 over\n");
pthread_rwlock_unlock(&rwlock);
return (void*)1;
}
void* thread_fun2(void *arg)
{
int err;
//pthread_rwlock_rdlock(&rwlock);
pthread_rwlock_wrlock(&rwlock);
printf("thread 2 print num %d\n",num);
sleep(5);
printf("thread 2 over\n");
pthread_rwlock_unlock(&rwlock);
return (void*)1;
}
int main()
{
pthread_t tid1,tid2;
int err;
err = pthread_rwlock_init(&rwlock,NULL);
if(err != 0)
{
printf("init rwlock failed\n");
return;
}
err = pthread_create(&tid1,NULL,thread_fun1,NULL);
if(err != 0)
{
printf("create new thread1 failed\n");
return;
}
err = pthread_create(&tid2,NULL,thread_fun2,NULL);
if(err != 0)
{
printf("create new thread 2failed\n");
return;
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_rwlock_destroy(&rwlock);
return 0;
}
思考:用多线程将一个文件1.c拷贝3个副本,11.c,12.c,13.c
360截图20200411093041428.jpg360截图20200411093156939.jpg
360截图20200411093353477.jpg
360截图20200411093600392.jpg
360截图20200411093802043.jpg
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#define BUFFER_SIZE 5 //产品库存大小
#define PRODUCT_CNT 30 //产品生成总数
struct product_cons
{
int buffer[BUFFER_SIZE]; //生产产品值
pthread_mutex_t lock; //互斥锁 volatile int
int readpos,writepos; //读写位置
pthread_cond_t notempty; //条件变量非空
pthread_cond_t notfull; //非满
}buffer;
void init(struct product_cons *p)
{
pthread_mutex_init(&p->lock,NULL); //互斥锁
pthread_cond_init(&p->notempty,NULL); //条件变量
pthread_cond_init(&p->notfull,NULL); //条件变量
p->readpos = 0;
p->writepos = 0;
}
void finish(struct product_cons *p)
{
pthread_mutex_destroy(&p->lock); //互斥锁
pthread_cond_destroy(&p->notempty); //条件变量
pthread_cond_destroy(&p->notfull); //条件变量
p->readpos = 0;
p->writepos = 0;
}
//存储一个数据到buffer
void put(struct product_cons *p,int data) //输入产品子函数
{
pthread_mutex_lock(&p->lock);
if((p->writepos+1) % BUFFER_SIZE == p->readpos)
{
printf("producer wait for not full\n");
pthread_cond_wait(&p->notfull,&p->lock);
}
p->buffer[p->writepos] = data;
p->writepos++;
if(p->writepos >= BUFFER_SIZE)
p->writepos = 0;
pthread_cond_signal(&p->notempty);
pthread_mutex_unlock(&p->lock);
}
//读,移除一个数据从buffer
int get(struct product_cons *p)
{
int data;
pthread_mutex_lock(&p->lock);
if(p->readpos == p->writepos)
{
printf("consumer wait for not empty\n");
pthread_cond_wait(&p->notempty,&p->lock);
}
data = p->buffer[p->readpos];
p->readpos++;
if(p->readpos >= BUFFER_SIZE)
p->readpos = 0;
pthread_cond_signal(&p->notfull);
pthread_mutex_unlock(&p->lock);
return data;
}
void *producer(void* data) //子线程,生产
{
int n;
for(n = 1;n <= 50;n++) //生成50个产品
{
sleep(1);
printf("put the %d product ...\n",n);
put(&buffer,n);
printf("put the %d product success\n",n);
}
printf("producer stopped\n");
return NULL;
}
void *consumer(void* data)
{
static int cnt = 0;
int num;
while(1)
{
sleep(2);
printf("get product ...\n");
num = get(&buffer);
printf("get the %d product success\n",num);
if(++cnt == PRODUCT_CNT)
break;
}
printf("consumer stopped\n");
return NULL;
}
int main(int argc,char* argv[])
{
pthread_t th_a,th_b;
void* retval;
init(&buffer);
pthread_create(&th_a,NULL,producer,0);
pthread_create(&th_b,NULL,consumer,0);
pthread_join(th_a,&retval);
pthread_join(th_b,&retval);
finish(&buffer);
return 0;
}
思考:多个生产者和消费者
360截图20200411193914860.jpg360截图20200411194257729.jpg
360截图20200411194317698.jpg
360截图20200411194514049.jpg
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
pthread_once_t once = PTHREAD_ONCE_INIT;
pthread_t tid;
void thread_init()
{
printf("I'm in thread 0x%x\n",tid);
}
void *thread_fun1(void* arg)
{
tid = pthread_self();
printf("I'm thread 1 0x%x\n",tid);
printf("once is %d\n",once);
pthread_once(&once,thread_init);
printf("once is %d\n",once);
return NULL;
}
void *thread_fun2(void* arg)
{
sleep(2);
tid = pthread_self();
printf("I'm thread 2 0x%x\n",tid);
pthread_once(&once,thread_init);
return NULL;
}
int main()
{
pthread_t tid1,tid2;
int err;
err = pthread_create(&tid1,NULL,thread_fun1,NULL);
if(err != 0)
{
printf("create new thread 1 failed\n");
return;
}
err = pthread_create(&tid2,NULL,thread_fun2,NULL);
if(err != 0)
{
printf("create new thread 2 failed\n");
return;
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return 0;
}
思考:将互斥量等初始化使用pthread_once实现。
360截图20200411195500756.jpg360截图20200411195610528.jpg 360截图20200411195636444.jpg
360截图20200411195652960.jpg
360截图20200411195805978.jpg
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
void *thread_fun1(void* arg)
{
printf("I'm thread 1 \n");
return (void*)1;
}
void *thread_fun2(void* arg)
{
printf("I'm thread 2\n");
return (void*)2;
}
int main()
{
pthread_t tid1,tid2;
int err;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
//pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);
err = pthread_create(&tid1,&attr,thread_fun1,NULL);
if(err != 0)
{
printf("create new thread 1 failed\n");
return;
}
err = pthread_create(&tid2,NULL,thread_fun2,NULL);
if(err != 0)
{
printf("create new thread 2 failed\n");
return;
}
err = pthread_join(tid1,NULL);
if(!err)
printf("join thread 1 success\n");
else
printf("join thread 1 failed\n");
err = pthread_join(tid2,NULL);
if(!err)
printf("join thread 2 success\n");
else
printf("join thread 2 failed\n");
pthread_attr_destroy(&attr);
return 0;
}
思考:设置线程的分离属性,然后在新县城中获取自己的分离属性。
360截图20200411200637349.jpg360截图20200411200902258.jpg
360截图20200411201053386.jpg
360截图20200411201105539.jpg
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <limits.h>
pthread_attr_t attr;
void *thread_fun(void* arg)
{
size_t stacksize;
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
pthread_attr_getstacksize(&attr, &stacksize);
printf("new thread stack size is %d\n",stacksize);
pthread_attr_setstacksize(&attr, 16389);
pthread_attr_getstacksize(&attr, &stacksize);
printf("new thread stack size is %d\n",stacksize);
#endif
printf("new thread stack size is %d\n",stacksize);
return(void*)1;
}
int main()
{
pthread_t tid;
int err;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
#endif
err = pthread_create(&tid,&attr,thread_fun,NULL);
if(err)
{
printf("create new thread failed\n");
return;
}
pthread_join(&tid,NULL);
//pthread_attr_destroy(&attr);
return 0;
}
360截图20200413081209017.jpg
360截图20200413081310718.jpg
360截图20200413081440824.jpg
360截图20200413081748055.jpg
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
int main()
{
char *shm = "myshm";
char *shm1 = "myshm1";
int shm_id,shm1_id;
char *buf;
pid_t pid;
pthread_mutex_t *mutex;
pthread_mutexattr_t mutexattr;
//打开共享内存
shm1_id = shm_open(shm1,O_RDWR|O_CREAT,0644);
//调整共享内存大小
ftruncate(shm1_id,100);
//映射共享内存,MAP_SHARED属性表明,对共享内存的任何修改都会影响其他进程
mutex = (pthread_mutex_t*)mmap(NULL,100,PROT_READ|PROT_WRITE,MAP_SHARED,shm1_id,0);
pthread_mutexattr_init(&mutexattr);
#ifdef _POSIX_THREAD_PROCESS_SHARED
pthread_mutexattr_setpshared(&mutexattr,PTHREAD_PROCESS_SHARED);
#endif
pthread_mutex_init(mutex,&mutexattr);
//打开共享内存
shm_id = shm_open(shm,O_RDWR|O_CREAT,0644);
//调整共享内存大小
ftruncate(shm_id,100);
//映射共享内存,MAP_SHARED属性表明,对共享内存的任何修改都会影响其他进程
buf = (char*)mmap(NULL,100,PROT_READ|PROT_WRITE,MAP_SHARED,shm_id,0);
pid = fork();
if(pid == 0)
{
//休眠1s,让父进程先运行
sleep(1);
printf("I'm child process\n");
pthread_mutex_lock(mutex);
//将共享内存内容修改为hello
memcpy(buf,"hello",6);
pthread_mutex_unlock(mutex);
printf("child buf is :%s\n",buf);
}
else if(pid > 0)
{
printf("I'm parent process\n");
pthread_mutex_lock(mutex);
//修改共享内存内容为world
memcpy(buf,"world",6);
sleep(3);
pthread_mutex_unlock(mutex);
printf("parent buf is : %s\n",buf);
}
pthread_mutexattr_destroy(&mutexattr);
pthread_mutex_destroy(mutex);
//解除映射
munmap(buf,100);
//消除共享内存
shm_unlink(shm);
//解除映射
munmap(mutex,100);
//消除共享内存
shm_unlink(shm1);
return 0;
}
- gcc -lrt :连接共享内存的库
360截图20200413083601975.jpg
思考:如果将互斥量的进程共享属性设为PTHREAD_PROCESS_PRIVATTE会是什么结果,为什么?
360截图20200413084019101.jpg
360截图20200413084715239.jpg
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
void *thread_fun1(void* arg)
{
printf("thread 1 start!\n");
open("1.c",O_RDWR);
sleep(2);
printf("thread 1 errno is :%d\n",errno);
}
void *thread_fun2(void *arg)
{
sleep(1);
printf("thread 2 start !\n");
open("t.c","O_RDWR");
printf("thread 2 errno is :%d\n",errno);
}
int main()
{
ptread_t tid1,tid2;
if(pthread_create(&tid1,NULL,thread_fun1,NULL));
{
printf("create new thread 1 failed\n");
return;
}
if(pthread_create(&tid2,NULL,thread_fun2,NULL));
{
printf("create new thread 2 failed\n");
return;
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
pthread_key_t key;
void *thread_fun1(void* arg)
{
printf("thread 1 start!\n");
int a = 1;
pthread_setspecific(key,(void*)a);
sleep(2);
printf("thread 1 key -->data is %d\n",pthread_getspecific(key));
}
void *thread_fun2(void *arg)
{
sleep(1);
printf("thread 2 start !\n");
int a = 2;
pthread_setspecific(key,(void*)a);
sleep(2);
printf("thread 2 key -->data is %d\n",pthread_getspecific(key));
}
int main()
{
pthread_t tid1,tid2;
pthread_key_create(&key,NULL);
if(pthread_create(&tid1,NULL,thread_fun1,NULL))
{
printf("create new thread 1 failed\n");
return;
}
if(pthread_create(&tid2,NULL,thread_fun2,NULL))
{
printf("create new thread 2 failed\n");
return;
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_key_delete(&key);
return;
}
思考:将一块动态申请的内存关联到key,访问pthread_getspecific(key),请注意内存的销毁。
360截图20200413090630982.jpg#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALLIZER;
void *thread_fun(void *arg)
{
sleep(1);
pid_t pid;
pid = fork();
if(pid == 0)
{
pthread_mutex_lock(&mutex);
printf("child\n");
pthread_mutex_unlock(&mutex);
}
if(pid > 0)
{
pthread_mutex_lock(&mutex);
printf("parent\n");
pthread_mutex_unlock(&mutex);
}
}
int main()
{
pthread_t tid;
if(pthread_create(&tid,NULL,thread_fun,NULL)
{
printf("create new thread failed\n");
return;
}
pthread_mutex_lock(&mutex);
sleep(2);
pthread_mutex_unlock(&mutex);
printf("main\n");
pthread_join(tid,NULL);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALLIZER;
void *thread_fun(void *arg)
{
sleep(1);
printf("new thread\n");
pid_t pid;
pthread_mutex_lock(&mutex);
pid = fork();
if(pid == 0)
{
pthread_mutex_unlock(&mutex);
printf("child\n");
}
if(pid > 0)
{
pthread_mutex_unlock(&mutex);
printf("parent\n");
}
}
int main()
{
pthread_t tid;
if(pthread_create(&tid,NULL,thread_fun,NULL)
{
printf("create new thread failed\n");
return;
}
printf("main\n");
pthread_join(tid,NULL);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALLIZER;
void prepare()
{
pthread_mutex_lock(&mutex);
printf("I'm prepare\n");
}
void parent()
{
pthread_mutex_unlock(&mutex);
printf("I'm parent\n");
}
void child()
{
pthread_mutex_unlock(&mutex);
printf("I'm child\n");
}
void *thread_fun(void *arg)
{
sleep(1);
pid_t pid;
pthread_atfork(prepare,parent,child);
pid = fork();
if(pid == 0)
{
pthread_mutex_lock(&mutex);
printf("child process\n");
pthread_mutex_unlock(&mutex);
}
if(pid > 0)
{
pthread_mutex_lock(&mutex);
printf("parent process\n");
pthread_mutex_unlock(&mutex);
}
}
int main()
{
pthread_t tid;
if(pthread_create(&tid,NULL,thread_fun,NULL)
{
printf("create new thread failed\n");
return;
}
pthread_mutex_lock(&mutex);
sleep(2);
printf("main\n");
pthread_mutex_unlock(&mutex);
pthread_join(tid,NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
360截图20200413092228289.jpg
360截图20200413092851137.jpg
360截图20200413093036581.jpg
360截图20200413093119391.jpg
360截图20200413093226285.jpg
360截图20200413093257429.jpg
360截图20200413093353172.jpg
360截图20200413093427388.jpg 360截图20200413093516998.jpg
360截图20200413093547124.jpg
360截图20200413093601791.jpg
//服务器
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAX_LISTEN 10
char buf[100];
int ad[10];
struct sockaddr_in server_ip,remote_ip;
int num = 0;
void *thread_fun(void *arg)
{
while(1)
{
printf("read data from client:%s\n",inet_ntoa(remote_ip.sin_addr.s_addr));
read(ad[(int)arg],buf,100);
printf("buf is %s\n",buf);
}
return NULL;
}
int main()
{
int server_len,remote_len;
pthread_t tid[10];
int err,sd,i=0;
sd = socket(AF_INET,SOCK_STREAM,0);
if(sd == -1)
{
printf("create socket failed,errno is %d\n",errno);
return;
}
server_ip.sin_family = AF_INET;
server_ip.sin_port = htons(5678);
server_ip.sin_addr.s_addr = htonl(INADDR_ANY);
memset(server_ip.sin_zero,0,8);
err = bind(sd,(struct sockaddr *)(&server_ip),sizeof(struct sockaddr));
if(err == -1)
{
printf("bind error,errno is %d\n",errno);
close(sd);
return;
}
err = listen(sd,MAX_LISTEN);
if(err == -1)
{
printf("listen error, errno is %d\n",errno);
close(sd);
return ;
}
remote_len = sizeof(struct sockaddr);
while(1)
{
ad[i] = accept(sd,(struct sockaddr*)(&remote_ip),&remote_len);
if(ad[i] == -1)
{
printf("accept error,errno is %d\n",errno);
close(sd);
return;
}
err = pthread_create(&tid[i],NULL,thread_fun,(void*)i);
if(err != 0)
{
printf("create new thread failed\n");
close(ad[i]);
}
i++;
close(ad[i]);
}
close(sd);
}
//客户端
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAX_LISTEN 10
char buf[100];
int sd;
struct sockaddr_in server_ip;
void *thread_write(void *arg)
{
while(1)
{
write(sd,"hello",6);
sleep(1);
}
return NULL;
}
void *thread_read(void *arg)
{
while(1)
{
sleep(1);
memset(buf,0,100);
read(sd,buf,100);
printf("client 2 say:%s\n",buf);
}
return NULL;
}
int main()
{
int server_len,remote_len;
pthread_t tid_read,tid_write;
int err,sd,i=0;
sd = socket(AF_INET,SOCK_STREAM,0);
if(sd == -1)
{
printf("create socket failed,errno is %d\n",errno);
return;
}
server_ip.sin_family = AF_INET;
server_ip.sin_port = htons(5678);
server_ip.sin_addr.s_addr = htonl(INADDR_ANY);
memset(server_ip.sin_zero,0,8);
err = connect(sd,(struct sockaddr *)(&server_ip),sizeof(struct sockaddr));
if(err == -1)
{
printf("connect error,errno is %d\n",errno);
close(sd);
return;
}
err = pthread_create(&tid_read,NULL,thread_read,NULL);
if(err)
{
printf("create read thread failed\n");
close(sd);
return ;
}
err = pthread_create(&tid_write,NULL,thread_write,NULL);
if(err)
{
printf("create read thread failed\n");
close(sd);
return ;
}
pthread_join(tid_read,NULL);
pthread_join(tid_write,NULL);
close(sd);
}
-
实现:
360截图20200413100826000.jpg
360截图20200413101728877.jpg
360截图20200413101817019.jpg
网友评论