您现在的位置是:主页 > news > 中上网站建设/seo引擎优化外包公司

中上网站建设/seo引擎优化外包公司

admin2025/5/5 20:53:33news

简介中上网站建设,seo引擎优化外包公司,个体户怎么做购物网站,家庭电脑做网站信号量 /********************* 信号量就相当于共享内存中的一个盒子, 把信号量初始化成多少就是最开始的时候往盒子里放了多少个信号! P操作就是从盒子里拿信号,只有盒子里有信号时才能拿, 若盒子里没有信号,你就只能…

中上网站建设,seo引擎优化外包公司,个体户怎么做购物网站,家庭电脑做网站信号量 /********************* 信号量就相当于共享内存中的一个盒子, 把信号量初始化成多少就是最开始的时候往盒子里放了多少个信号! P操作就是从盒子里拿信号,只有盒子里有信号时才能拿, 若盒子里没有信号,你就只能…


信号量
/*********************
信号量就相当于共享内存中的一个盒子,
把信号量初始化成多少就是最开始的时候往盒子里放了多少个信号!
P操作就是从盒子里拿信号,只有盒子里有信号时才能拿,
若盒子里没有信号,你就只能在盒子旁边等到什么时候盒子里有信号了,拿到信号才能走!
V操作就是往盒子里放信号,不管盒子里有没有信号,你都可以往里面放信号!

*********************/

一.【信号量是】在计算机中用来模拟信号灯的一个【整数】
当这个整数变为非0才能进行某种操作许可;
在进行操作的同时,将该整数减1,以此改变信号灯,
将减1操作称为P操作,也称获取信号;
当该操作进行完之后,将该整数加1,以此来恢复信号灯,
将加1操作称为V操作,也称释放信号;

信号量的原理可以模拟为一下代码:
int i=N;        //初始化信号量
if(i != 0)
{
    i--;    //可以进行P操作
    //i++    //也可以进行V操作
    进行某种操作.....
    i++;    //V操作
}
else    if(i == 0)
{
    i++;    //只能进行V操作
}

二.进程中使用信号量:
1.获取key,使用函数ftok()
key_t key=ftok("/home",'a');
"/home":字符串形式的文件路径,要求必须存在且可访问
'a'    :整型的项目ID,要求非0,低8位被使用,一般写一个字符

2.创建/获取信号量,使用函数semget()函数
int semid = semget(key,1,0777 | IPC_CREAT);
key:    ftok的返回值
1:        信号量的个数
0777 | IPC_CREAT:    标志,可用    IPC_CREAT   IPC_EXCL    
注:创建新的信号量时,需要指定权限,如0664 | IPC_CREAT

3.初始化信号量,使用函数semctl()函数
int res = semctl(semid,0,SETVAL,1);
if(res < 0)
{
    perror("semctl");
    exit(-1);
}
semid:semid,semget的返回值
0:信号量的下标
SETVAL:操作命令
    IPC_RMID        删除信号量,不需要第四个参数
    IPC_SETVAL        使用第4个参数的值初始化信号量
1:可变参数,是否需要由第三参数决定 

4.定义结构体指针
    struct sembuf
    {
        unsigned short sem_num;  /* 信号量所在下标 */
        short sem_op;   /* 具体操作,正数增加,负数减少*/
        short sem_flg;  /* 标志 IPC_NOWAIT and SEM_UNDO. */
    };

5.初始化结构体指针
P操作:
sb.sem_num = 0;        
sb.sem_op = -1;        //P操作将其初始化为-1
sb.sem_flg = SEM_UNDO;
V操作:
sb.sem_num = 0;
sb.sem_op = 1;            //V操作将其初始化为1
sb.sem_flg = SEM_UNDO;

6.操作信号量,使用函数semop()函数
int res = semop(semid,&sb,1);
if(res < 0)
{
    perror("semop");
    exit(-1);
}
semid:获取的信号量
&sb:结构体指针
    struct sembuf
    {
        unsigned short sem_num;  /* 信号量所在下标 */
        short sem_op;   /* 具体操作,正数增加,负数减少*/
        short sem_flg;  /* 标志 IPC_NOWAIT and SEM_UNDO. */
    };
1:结构体指针指向的结构体数组的元素个数

ps:访问共享资源

7.删除信号量,使用函数semctl()函数
int semctl(semid,0,IPC_RMID);
semid:获取的信号量
0:信号量的下标
IPC_RMID:删除信号量,不需要第四个参数代码实例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>struct sembuf sb;
char *s="exit";
void p(int semid)
{sb.sem_num = 0;        sb.sem_op = -1;sb.sem_flg = SEM_UNDO;int res = semop(semid,&sb,1);if(res < 0){perror("sem_op  p");exit(-1);}return ;
}
void v(int semid)
{sb.sem_num = 0;sb.sem_op = 1;sb.sem_flg = SEM_UNDO;int res = semop(semid,&sb,1);if(res < 0){perror("sem_op   v");exit(-1);}return ;
}
int main()
{//1.生成keykey_t key=ftok("/home",'a');if(key < 0){perror("ftok");exit(-1);    //直接结束进程}//2.1 创建信号量int semid = semget(key,1,0777 | IPC_CREAT);if(semid < 0){perror("semget");exit(-1);}//2.2创建共享内存int shmid = shmget(key,4096,0777 | IPC_CREAT);if(shmid < 0){perror("shmget");exit(-1);}//3.1 初始化信号量int res = semctl(semid,0,SETVAL,1);if(res < 0){perror("semctl");exit(-1);}    //3.2 映射共享内存void *addr = (void *)shmat(shmid,NULL,0);//0是标志,代表可读可写if(addr == (void *)-1){perror("shmat");exit(-1);}    //4.创建进程pid_t pid = fork();if(pid < 0){perror("fork");exit(-1);}else if(pid == 0){        //子进程中接收并打印共享内存中的数据while(1){if(!strcmp(addr,s)){//8.解除子进程的映射shmdt(addr);                //9.删除共享内存shmctl(shmid,IPC_RMID,NULL);break;}        //6.打印共享内存中数据            p(semid);printf("semid buf = %s\n",(char *)addr);v(semid);}exit(0);}else if(pid > 0){    //父进程中写数据存入共享内存while(1){//5.写数据存入共享内存p(semid);char buf[1024] = {0};scanf("%s",buf);                //写数据存入缓存区memcpy(addr,buf,sizeof(buf));     //将缓存区中数据拷贝到共享内存中v(semid);printf("buf = %s\n",buf);       //打印要写入的数据if(!strcmp(buf,s)){break;}    }//7.解除父进程的映射shmdt(addr);wait(NULL);}    return 0;
}


}

三.线程中使用信号量
1.定义一个信号量
sem_t    sem;

2.初始化信号量    sem_init()函数
sem_init(&sem,0,1);
&sem:    定义的信号量的地址
第二个参数:0:表示同一进程中的线程间共享,非0:进程间共享
1:    信号量的初始值
注:sem处信号量为同一进程中线程共享的信号量,
信号的初始值为1,即P、V操作从1开始

3.获取信号量(即P操作)
sem_wait(&sem);
&sem:定义的信号量的地址

ps:访问共享资源

4.释放信号量(即V操作)
sem_post(&sem);
&sem:定义的信号量的地址

5.销毁信号量
sem_destroy(&sem);
&sem:定义的信号量的地址代码实例:

#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
#include <semaphore.h>int count = 0;                
sem_t sem;//定义信号量
//线程函数
void *thread_func(void *arg)
{sem_wait(&sem);        //获取信号量int *p = (int*)arg;    //获得线程创建时传进来的参数int num = *p;printf("child num = %d\n",num);int i;for(i = 0; i < num; i++){count++;}sem_post(&sem);    //释放信号量
}
int main()
{int i;int num = 1000000;int res;pthread_t tid[2];        sem_init(&sem,0,1);    //初始化信号量    //创建两个线程,线程ID保存在数组tid中for(i = 0; i < 2; i++){res = pthread_create(&tid[i],NULL,thread_func,(void*)&num);if(res != 0){fprintf(stderr,"thread create error: %s\n",strerror(res));exit(-1);}printf("creat new thread id = %lu\n",tid[i]);}//等待线程结束for(i = 0; i < 2; i++){pthread_join(tid[i],NULL);printf("thread %d exited!!\n",i);}printf("count  =  %d\n",count);sem_destroy(&sem);    //不再使用,销毁信号量return 0;
}

【用多个信号量控制访问的先后顺序】:
    sem_t sem1;
    sem_t sem2;

1.将需要优先访问的线程/进程初始化成非0;
    sem_init(&sem1,0,1);
2.将后访问的线程/进程初始化成0;
    sem_init(&sem2,0,0);
3.在优先访问的线程/进程的访问过程中对需要后访问的线程/进程
进行V操作
    sem_wait(&sem1);
    执行任务。。。。。
    任务完成
    sem_post(&sem2);
4.此时后访问的进程才可以访问,在访问过程中对需要先访问的线程/进程
进行V操作
    sem_wait(&sem2);    
    sem_post(&sem1);
【程序执行流程】:先执行sem1,碰到sem_post(&sem2);后,
sem1休眠,立即执行sem2,碰到sem_post(&sem1);后,
继续执行后面的任务,执行完后再去执行sem1中sem_post(&sem2);后面的程序