欢迎来到皮皮网网首页

【idea源码部署】【工业网关源码下载】【源码调试和编译】sleep函数源码_sleep函数源码分析

来源:易企微源码 时间:2024-11-25 05:58:16

1.sleep����Դ��
2.Kswapd 源码解析
3.go源码:Sleep函数与线程
4.如何让 Qt 的程序使用 Sleep

sleep函数源码_sleep函数源码分析

sleep����Դ��

       // 项目三—学员管理系统.cpp : 定义控制台应用程序的函函数入口点。

       //

       #include "stdafx.h"

       #include<string.h>

       #include<windows.h>

       int k=0;

       struct Student

       {

        int no;

        char name[];

        float score[3];

        float avg;

        float sum;

       }stu[],数源shuchu[];

       void print(int a); //输出函数

       void menu(); //目录

       void one(); //选择一

       void two(); //选择二

       void three(Student stu1[]); //选择三

       void fore(); //选择四

       void five(); //选择五

       void six(); //选择六

       void sever(); //选择七

       void eight(); //选择八

       void nine(); //选择九

       void xuanzhe(int a); //选择函数

       int chongfu(Student stu[],int a); //判断学号是否重复

       int PDmingzi(Student st[],int num); //判断名字是否合法

       void fanhui(); //是否返回主菜单

       void fuzhi(Student a[],int num);

       int _tmain(int argc, _TCHAR* argv[])

       {

        //登陆模板

        char user[];

        char passwork[];

        int count=0;

        while (count<3)

        {

        printf("\n\n\t\t请输入用户名:");

        gets_s(user);

        printf("\t\t请输入密码:");

        gets_s(passwork);

        if(strcmp(user,"admin")==0&&strcmp(passwork,"")==0)

        {

        system("cls");

        printf("\n\n\t\t登陆成功");

        Sleep();printf(">");Sleep();printf(">");Sleep();printf(">");Sleep();printf(">");

        Sleep();printf(">");Sleep();printf(">");Sleep();Sleep();printf(">");Sleep();

        printf(">");

        menu();//调用菜单函数

        break;

        }

        else

        {

        if (count==2)

        {

        printf("\t提示:您输入用户和密码错误次数过多,请稍后再试!源码\n");

        system("cls");

        break;

        }

        else

        {

        printf("\n\n\t\t登陆失败!分析请重新输入!函函数\n");

        }

        count++;

        system("cls");

        }

        }

        return 0;

       }

       //菜单

       void menu()

       {

        system("cls");

        int count=0;

        while(count<3)

        {

        printf("\n\t\t学 员 管 理 系 统 平 台\n");

        printf("---------------------------------\n");

        printf("\t◎功能菜单:\n");

        printf("\n\t\t-----------------------------\n");

        Sleep();

        printf("\t\t1、数源idea源码部署单个学员的源码信息循环录入\n");

        printf("\t\t------------------------------\n");

        printf("\t\t2、显示所有学员的分析信息\n");

        printf("\t\t------------------------------\n");

        printf("\t\t3、排序显示所有学员信息\n");

        printf("\t\t------------------------------\n");

        printf("\t\t4、函函数插入单个学员信息\n");

        printf("\t\t------------------------------\n");

        printf("\t\t5、数源删除单个学员信息\n");

        printf("\t\t------------------------------\n");

        printf("\t\t6、源码查找单个学员信息\n");

        printf("\t\t------------------------------\n");

        printf("\t\t7、分析读取所有学员信息\n");

        printf("\t\t------------------------------\n");

        printf("\t\t8、函函数保存所有学员信息\n");

        printf("\t\t------------------------------\n");

        printf("\t\t9、数源退出程序\n");

        printf("\t\t------------------------------\n");

        printf("请选择:");

        char a;

        int b;

        fflush(stdin);

        a=getchar();

        if (a>=(1+'0')&&a<=(9+'0'))

        {

        b=(int)a-'0';

        xuanzhe(b);

        }

        else

        {

        count++;

        if (count==2)

        {

        system("cls");

        printf("错误次数过多!源码");

        break;

        }

        }

        }

       }

       //选择

       void xuanzhe(int a)//选择

       {

        switch (a)

        {

        case 1:

        system("cls");

        one();

        break;

        case 2:

        system("cls");

        two();

        break;

        case 3:

        system("cls");

        three(stu);

        fanhui();

        break;

        case 4:

        system("cls");

        fore();

        break;

        case 5:

        system("cls");

        five();

        break;

        case 6:

        system("cls");

        six();

        fanhui();

        break;

        case 7:

        system("cls");

        sever();

        break;

        case 8:

        system("cls");

        eight();

        break;

        case 9:

        system("cls");

        nine();

        break;

        default:

        break;

        }

       }

       //1

       void one()

       {

        char s;

        printf("1、单个成绩循环录入:\n");

        while (true)//接收输入的工业网关源码下载

        {

        while(true)

        {

        printf("学号:");

        scanf_s("%d",&stu[k].no);

        if (chongfu(stu,k))

        {

        printf("学号重复请重新输入!\n");

        }

        else

        {

        break;

        }

        }

        while (true)

        {

        printf("姓名:");

        fflush(stdin);

        gets_s(stu[k].name);

        int a=strlen(stu[k].name);

        if (a==0)

        {

        printf("提示:名字不能为空,请重新输入!\n");

        }

        else if(PDmingzi(stu,a))

        {

        printf("提示:名字不能为数字,请重新输入!\n");

        }

        else

        {

        break;

        }

        }

        for (int i = 0; i < 3; i++)

        {

        printf("成绩%d:",i+1);

        scanf_s("%f",&stu[k].score[i]);

        if (!(stu[k].score[i]<=&&stu[k].score[i]>=0))

        {

        i--;

        printf("输入有误!!请重新输入\n");

        continue;

        }

        }

        stu[k].sum=stu[k].score[0]+stu[k].score[1]+stu[k].score[2];

        stu[k].avg=stu[k].sum/3.0;

        while (true)

        {

        printf("是否继续录入Y/N?");

        fflush(stdin);

        s=getchar();

        if (s=='N'||s=='n')

        {

        fuzhi(stu,k);

        print(k);

        printf("是否返回主菜单(Y/N):");

        char a;

        fflush(stdin);

        a=getchar();

        if (a=='y'||a=='Y')

        {

        menu();

        }

        }

        else if (s=='y'||s=='Y')

        {

        break;

        }

        else

        {

        printf("你的输入有误!请重新输入!\n");

        }

        }

        k++;

        }

       }

       //读正输入的

       void print(int a)

       {

        printf("学号\t姓名\t成绩一\t成绩二\t成绩三\t总成绩\t平均分\n");

        for (int i = 0; i <=a ; i++)

        {

        printf("%d\t%s\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n",shuchu[i].no,shuchu[i].name,shuchu[i].score[0],shuchu[i].score[1],shuchu[i].score[2],shuchu[i].sum,shuchu[i].avg);

        }

       }

       void two()

       {

        printf("学员信息:\n");

        fuzhi(stu,k);

        print(k);

        fanhui();

       }

       void three(Student stu1[])

       {

        //根据平均分降排序所有学员信息

        for (int i = 0; i <k ; i++)

        {

        for (int j = 0; j < k-i; j++)

        {

        if (stu1[j].avg<stu[j+1].avg)

        {

        Student temp;

        temp=stu1[j];

        stu1[j]=stu1[j+1];

        stu1[j+1]=temp;

        }

        }

        }

        fuzhi(stu1,k);

        print(k);

       }

       void fore()

       {

        three(stu);

        printf("1、插入单个学生信息:\n");

        while (true)//接收输入的

        {

        if (k>0)

        k++;

        while(true)

        {

        printf("学号:");

        scanf_s("%d",&stu[k].no);

        if (chongfu(stu,k))

        {

        printf("学号重复请重新输入!\n");

        }

        else

        {

        break;

        }

        }

        while (true)

        {

        printf("姓名:");

        fflush(stdin);

        gets_s(stu[k].name);

        int a=strlen(stu[k].name);

        if (a==0)

        {

        printf("提示:名字不能为空,请重新输入!\n");

        }

        else if(PDmingzi(stu,a))

        {

        printf("提示:名字不能为数字,请重新输入!\n");

        }

        else

        {

        break;

        }

        }

        for (int i = 0; i < 3; i++)

        {

        printf("成绩%d:",i+1);

        scanf_s("%f",&stu[k].score[i]);

        if (!(stu[k].score[i]<=&&stu[k].score[i]>=0))

        {

        i--;

        printf("输入有误!!源码调试和编译请重新输入\n");

        continue;

        }

        }

        stu[k].sum=stu[k].score[0]+stu[k].score[1]+stu[k].score[2];

        stu[k].avg=stu[k].sum/3.0;

        char s;

        while (true)

        {

        printf("是否继续插入Y/N?");

        fflush(stdin);

        s=getchar();

        if (s=='N'||s=='n')

        {

        system("cls");

        fanhui();

        }

        else if (s=='y'||s=='Y')

        {

        break;

        }

        else

        {

        printf("你的输入有误!请重新输入!\n");

        }

        }

        }

       }

       void five()

       {

        //删除单个学员的信息

        print(k);

        printf("请输入要删除的学员信息的学号:");

        int num;

        scanf_s("%d",&num);

        int i;

        for ( i= 0; i <= k; i++)

        {

        if (stu[i].no==num)

        {

        break;

        }

        }

        for (int j = i; j <= k; j++)

        {

        stu[i]=stu[i+1];

        }

        k-=1;

        fanhui();

       }

       void six()

       {

        Student a[1];

        while (true)

        {

        printf("请输入要查找的学员信息的学号:");

        int num;

        scanf_s("%d",&num);

        int i;

        for ( i= 0; i <= k; i++)

        {

        if (stu[i].no==num)

        {

        a[0]=stu[i];

        fuzhi(a,0);

        print(0);

        }

        }

        }

       }

       void sever()

       {

        FILE *p;

        fopen_s(&p,"d:\\项目三存储.txt","rb");

        if (p!=NULL)

        {

        int n=fread(stu,sizeof(struct Student),,p);

        if (k==0)

        {

        k=n-1;

        }

        }

        fclose(p);

       }

       void eight()

       {

        FILE *fp;

        fopen_s(&fp,"d:\\项目三存储.txt","wb");

        fwrite(&stu,sizeof(struct Student),k+1,fp);

        fflush(fp);

        fclose(fp);

        printf("保存成功!\n");

        fanhui();

       }

       void nine()

       {

        exit(1);

       }

       int chongfu(Student stu[],int a)

       {

        for (int i = 0; i < a; i++)

        {

        if (stu[a].no==stu[i].no)

        {

        return 1;

        }

        }

        return 0;

       }

       int PDmingzi(Student st[],int num)

       {

        for (int i = 0; i <= num; i++)

        {

        if(st[k].name[i]>='0'&&st[k].name[i]<='9')

        {

        return 1;

        }

        }

        return 0;

       }

       void fuzhi(Student a[],int num)

       {

        for (int i = 0; i <= num; i++)

        {

        shuchu[i]=a[i];

        }

       }

       void fanhui()

       {

        printf("是否返回主菜单(Y/N):");

        char a;

        fflush(stdin);

        a=getchar();

        if (a=='y'||a=='Y')

        {

        menu();

        }

       }

Kswapd 源码解析

       kswapd是Linux内核中的一个内存回收线程,主要用于内存不足时回收内存。初始化函数为kswapd_init,内核为每个节点分配一个kswapd进程。每个节点的pg_data_t结构体中维护四个成员变量,用于管理kswapd线程。

       在初始化后,每个节点的kswapd线程进入睡眠状态。唤醒时机主要在被动唤醒和主动唤醒两种场景:被动唤醒是内存分配进程唤醒并完成异步内存回收后,对节点内存环境进行平衡度检查,若平衡则线程短暂休眠ms后主动唤醒。主动唤醒是内存回收策略调用kswapd,对节点进行异步内存回收,视频码源码下载让节点达到平衡状态。

       内存回收包括快速和直接两种方式,但系统周期性调用kswapd线程平衡不满足要求的节点,因为有些任务内存分配不允许阻塞或激活I/O访问,回收内存相当于亡羊补牢,系统利用空闲时间进行内存回收是必要的。

       kswapd线程通过module_init(kswapd_init)创建,一般处于睡眠状态等待被唤醒,当系统内存紧张时,会唤醒kswapd线程,调整不平衡节点至平衡状态。

       kswapd函数包含alloc_order、reclaim_order和classzone_idx三个变量,用于控制线程执行流程。kswapd_try_to_sleep函数判断是否睡眠并让出CPU控制权,同时是ucosii源码如何下载线程唤醒的入口。balance_pgdat函数是实际内存回收操作,涉及内存分配失败后唤醒kswapd线程,调用此函数对指定节点进行异步内存回收。

       kswapd_shrink_node函数通过shrink_node对低于sc->reclaim_idx的非平衡zone区域进行回收。

       总结kswapd执行流程,其生命周期与Linux操作系统相似,平时处于睡眠状态让出CPU控制权。在内存紧张时被唤醒,有被动唤醒和周期性主动唤醒两种时机。被动唤醒发生在内存分配任务获取不到内存时,表明系统内存环境紧张,主动唤醒则是内存回收策略的执行。线程周期性唤醒在被动唤醒后的短暂时间内,原因在于系统内存环境紧张,需要在这段时间内进行内存回收。

go源码:Sleep函数与线程

       在探索 Go 语言的并发编程中,Sleep 函数与线程的交互方式与 Java 或其他基于线程池的并发模型有所不同。本文将深入分析 Go 语言中 Sleep 函数的实现及其与线程的互动方式,以解答关于 Go 语言中 Sleep 函数与线程关系的问题。

       首先,重要的一点是,当一个 goroutine(g)调用 Sleep 函数时,它并不会导致当前线程被挂起。相反,Go 通过特殊的机制来处理这种情景,确保 Sleep 函数的调用不会影响到线程的执行。这一特性是 Go 语言并发模型中独特而关键的部分。

       具体来说,当一个 goroutine 调用 Sleep 函数时,它首先将自身信息保存到线程的关键结构体(p)中并挂起。这一过程涉及多个函数调用,包括 `time.Sleep`、`runtime.timeSleep`、`runtime.gopark`、`runtime.mcall`、`runtime.park_m`、`runtime.resetForSleep` 等。最终,该 goroutine 会被放入一个 timer 结构体中,并将其放入到 p 关联的一个最小堆中,从而实现了对当前 goroutine 的保存,同时为调度器提供了切换到其他 goroutine 或 timer 的机会。因此,这里的 timer 实际上代表了被 Sleep 挂起的 goroutine,它在睡眠到期后能够及时得到执行。

       接下来,我们深入分析 goroutine 的调度过程。当线程 p 需要执行时,它会通过 `runtime.park_m` 函数调用 `schedule` 函数来进行 goroutine 或 timer 的切换。在此过程中,`runtime.findrunnable` 函数会检查线程堆中是否存在已到期的 timer,如果存在,则切换到该 timer 进行执行。如果 timer 堆中没有已到期的 timer,线程会继续检查本地和全局的 goroutine 队列中是否还有待执行的 goroutine,如果队列为空,则线程会尝试“偷取”其他 goroutine 的任务。这一过程包括了检查 timer 堆、偷取其他 p 中的到期 timer 或者普通 goroutine,确保任务能够及时执行。

       在“偷取”任务的过程中,线程会优先处理即将到期的 timer,确保这些 timer 的准时执行。如果当前线程正在执行其他任务(如 epoll 网络),则在执行过程中会定期检查 timer 到期情况。如果发现其他线程的 timer 到期时间早于自身,会首先唤醒该线程以处理其 timer,确保不会错过任何到期的 timer。

       为了证明当前线程设置的 timer 能够准时执行,本文提出了两种证明方法。第一种方法基于代码细节,重点分析了线程状态的变化和 timer 的执行流程。具体而言,文章中提到的三种线程状态(正常运行、epoll 网络、睡眠)以及相应的 timer 执行情况,表明在 Go 语言中,timer 的执行策略能够确保其准时执行。第二种方法则从全局调度策略的角度出发,强调了 Go 语言中线程策略的设计原则,即至少有一个线程处于“spinning”状态或者所有线程都在执行任务,这保证了 timer 的准时执行。

       总之,Go 语言中 Sleep 函数与线程之间的交互方式,通过特殊的线程管理机制,确保了 goroutine 的 Sleep 操作不会阻塞线程,同时保证了 timer 的准时执行。这一机制是 Go 语言并发模型的独特之处,为开发者提供了一种高效且灵活的并发处理方式。

如何让 Qt 的程序使用 Sleep

       Qt 为何没有提供 Sleep

       è®ºå›ä¸Šä¸æ—¶è§åˆ°æœ‰äººé—®ï¼š

       Qt 为什么没有提供跨平台的 sleep 函数?

       ä½¿ç”¨å¹³å°ç›¸å…³çš„ Sleep 或 nanosleep 以后,界面为什么没有反应?

       QThread 中提供了protected 权限的 sleep 函数,如何用到主线程中?

       ä½¿ç”¨ QTest 中的 qSleep,在windows下如何隐藏控制台?

       è¿™äº›é—®é¢˜å…¶å®žå½’结为一点:在主线程中使用这些函数是一种错误,这会直接导致界面无法刷新,用户与程序无法交互。

       Qt不提供,是因为你不需要在主线程中使用 sleep 函数。

       å¦‚何让程序等待一段时间

       QTime

       QTime t;

       t.start();

       while(t.elapsed()<);

       è¿™ç§æ­»å¾ªçŽ¯ä¹Ÿæ˜¯ä¸€ç§å¸¸è§é”™è¯¯ç”¨æ³•ã€‚但改成正确的还是比较简单的:

       QTime t;

       t.start();

       while(t.elapsed()<)

        QCoreApplication::processEvents();

       ä¸åœåœ°å¤„理事件,以使得程序保持响应。

       QElapsedTimer

       è¿™æ˜¯Qt4.7引入的新的类,和QTime相比,它提供了更快的计算 elapsed 时间的方法。

       QElapsedTimer t;

       t.start();

       while(t.elapsed()<)

        QCoreApplication::processEvents();

       QTest::qWait

       è¿™æ˜¯QTest模块提供的等待函数

       ä¸‹é¢æ˜¯å…¶æºä»£ç ï¼ˆå’Œæˆ‘们前面的代码很像吧?):

       namespace QTest

       {

        inline static void qWait(int ms)

        {

        Q_ASSERT(QCoreApplication::instance());

        QElapsedTimer timer;

        timer.start();

        do {

        QCoreApplication::processEvents(QEventLoop::AllEvents, ms);

        QTest::qSleep();

        } while (timer.elapsed() < ms);

        }

       ...

       å…¶å®žæ²¡ä»€ä¹ˆé­”力,对吧?但是因为它QTest模块,所以在程序中我们不要使用它。

       QEventLoop

       é…åˆQTimer使用局部的 eventLoop 也是一个不错的选择。例子:

        QEventLoop eventloop;

        QTimer::singleShot(, &eventloop, SLOT(quit()));

        eventloop.exec();

       QTimer 和 QBasicTimer

       è¿™ä¸¤ä¸ªå’Œæœ¬æ–‡æ²¡æœ‰ä»€ä¹ˆç›´æŽ¥å…³ç³»ï¼ŒQTimer估计大家都很熟了。而QBasicTimer估计很少有人用。

       ä¸ŽQTimer相比,QBasicTimer更快速、轻量、底层。

       ä¸ŽQTimer相比,它不是QObject的派生类。

       è·¨å¹³å°çš„sleep

       å°½ç®¡ä¸€å¼€å§‹æˆ‘们就说了,不需要这个东西。但不排除某种场合下,你确实需要这个东西。如何实现一个跨平台的 sleep 呢?

       æˆ‘们一开始也提到了,QThreadç±» 和 QTest模块都提供了sleep函数,其实我们只需要看看他们的源码就够了:

       QTest 模块中的函数很简单(windows下调用Sleep,其他平台调用 nanosleep):

       void QTest::qSleep(int ms)

       {

        QTEST_ASSERT(ms > 0);

       #ifdef Q_OS_WIN

        Sleep(uint(ms));

       #else

        struct timespec ts = { ms / , (ms % ) * * };

        nanosleep(&ts, NULL);

       #endif

       }

       çœ‹QThread的源码,windows下同样直接调用Sleep,但非windows的实现比这个就复杂多了:

       [cpp] view plain copy

       /* /internal

        helper function to do thread sleeps, since usleep()/nanosleep()

        aren't reliable enough (in terms of behavior and availability)

       */

       static void thread_sleep(struct timespec *ti)

       {

        pthread_mutex_t mtx;

        pthread_cond_t cnd;

        pthread_mutex_init(&mtx, 0);

        pthread_cond_init(&cnd, 0);

        pthread_mutex_lock(&mtx);

        (void) pthread_cond_timedwait(&cnd, &mtx, ti);

        pthread_mutex_unlock(&mtx);

        pthread_cond_destroy(&cnd);

        pthread_mutex_destroy(&mtx);

       }

       void QThread::sleep(unsigned long secs)

       {

        struct timeval tv;

        gettimeofday(&tv, 0);

        struct timespec ti;

        ti.tv_sec = tv.tv_sec + secs;

        ti.tv_nsec = (tv.tv_usec * );

        thread_sleep(&ti);

       }