操作系统实验

article/2025/10/29 3:36:59

实验一 命令解释程序

实验内容

利用C语言编写一个微型命令解释程序minishell.c,该程序可接收并解释以下命令:
(1) dir 列出当前目录
(2) cop file1 file2 拷贝文件
(3) era filename 删除文件
(4) disp string 显示字符串
(5) end 结束,退出
要求:
(1)检查命令的合法性,如果有错误,显示出错信息,等待重新输入;
(2)命令前后有空格示为合法命令。

实验预备内容

  • gets() 读入字符串,直到回车结束,但是不包括回车
  • strcspn(str1,str2) 返回str1开头连续不包含str2的字符串
  • strncpy(str1,str2,n) 将str2字符串的前n个复制到str1中
  • strcmp(str1,str2) 将str1和str2进行比较
    • 返回值小于0,str1 < str2
    • 等于零 str1 == str2
    • 大于零 str1 > str2
  • system(command) 执行command

示例程序

#define true 1
#define false 0#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main(){char cmdl[80];char *scwt[] = {"exit","dir","time"};static int cmdnum = 3;  // 可用命令数char cmd[80];int j,n;while(true){printf("Please input command:");gets(cmdl); // 取命令行输入n = strcspn(cmdl," ");// 取命令部分if(n > 0 || strlen(cmdl) > 0){strncpy(cmd,cmdl,n);// 构成字符串cmd[n] = '\0';for(j = 0;j < cmdnum;j++){if(strcmp(cmdl,scwt[j]) == 0) break;}if(j == 0) exit(0);if(j < cmdnum){system(cmdl);continue;}printf("Bad command!\n");}}
}

实验代码

暂时先不放出来
在这里插入图片描述

实验二 进程管理

实验内容
1、进程的创建
编写一段程序,使用系统调用fork()创建两个子进程。让父进程显示字符串‘Parent:’;两个子进程分别显示字符串‘Child1:’和‘Child2:’。多次运行此程序,观察屏幕显示的结果,并分析原因。
2、进程控制
修改已编写的程序,将输出多次重复的一句话,观察程序执行时在屏幕上显示的结果,并分析原因。
若在程序中使用系统调用lockf()来给每一个进程加锁,可以实现进程之间的互斥,观察屏幕显示的结果,并分析原因。

实验预备内容和示例程序

fork 的测试

fork的功能描述:

  • fork()通过复制进程来创建一个新进程。子进程类似于当前进程的副本,但是:
    • 子进程有自己唯一的进程ID,而且这个进程的PID与任何进程的ID都不相同
    • 子进程的父进程ID等于父进程的进程ID
  • 返回值:
    • 如果成功,在父进程中返回子进程的PID,在子进程中返回0
    • 失败了,在父进程中返回-1,没有创建子进程
crescent_p@CP:~/Program/Experiment2$ gcc -o fork1 forkTest1.c 
crescent_p@CP:~/Program/Experiment2$ ./fork1 
fork test
fork test
#include <stdio.h>
#include <unistd.h>int main(){fork();printf("fork test\n");return  0;
}

分析:为什么输出了两次?

  • 程序运行开始就创建了一个进程
  • 当进程执行fork之后,创建了一个子进程
    • 子进程的代码是父进程代码的副本
    • 子进程的代码执行进度和父进程创建子进程时代码执行进度一致

测试二:

#include <stdio.h>
#include <unistd.h>int main(){pid_t pid;pid = fork();// 父进程if(pid > 0){printf("I am father\n");}if(pid == 0){printf("I an son\n");}if(pid < 0){printf("fork error\n");}printf("main over\n");return 0;
}

image-20210928193608909

分析为什么结果不一样:

  • 为什么又会出现son又会出现father?
    • 在父进程中,fork()返回子进程的PID,大于0,因此会执行第一个if
    • 在子进程中,fork()返回子进程的PID,等于0,因此会执行第二个if
  • 为什么两次执行这个可执行文件结果不一样?
    • 进程的异步性,我们设父进程为p1,子进程为p2
    • 第一个执行:
      • p1执行完第一个if,就轮到p2上处理机运行
    • 第二个执行:
      • p1执行完,才轮到p2上处理机

测试三:

#include <stdio.h>
#include <unistd.h>int main(){printf("执行到fork函数之前其进程为 %d,其父进程为 %d\n",getpid(),getppid());sleep(1);fork();printf("这个进程id为:%d,它的父进程为%d\n",getpid(),getppid());return 0;
}

在这里插入图片描述
测试四:

#include <stdio.h>
#include <unistd.h>
int main(){pid_t p1,p2;while((p1 = fork()) == -1);// 子进程if(p1 == 0) { puts("b");}else {puts("a");}return 0;
}

实验代码

暂时先不放出来
image-20210928200118428
image-20210928202915931
image-20210928203604575

实验三进程间的通信

管道通信

实验预备内容和示例程序

测试 pipe():

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>int main(){pid_t pid;int fd[2];char buf[50],s[50];// 创建了管道,半双工pipe(fd);while((pid = fork()) == -1);// 子进程if(pid == 0){sprintf(buf,"Child is sending message!");// fd[1] 写入管道write(fd[1],buf,50);// exit 在退出前,还会把文件缓冲区中的内容写回文件// 退出进程,其实是变成了一个僵尸进程exit(0);}else{// 进程一旦调用了wait,就立即阻塞自己// 由wait自动分析是否当前进程的某个子进程已经退出// 如果让它找到了这样一个已经变成僵尸的子进程// wait就会收集这个子进程的信息,并把它彻底销毁后返回// 如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。wait(0);// fd[0] 读取管道,将管道中的内容读入到s中read(fd[0],s,50);printf("%s\n",s);exit(0);}return 0;
}

image-20210930160345642

一个管道

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>int main(){// 通道数组int fd[2];pid_t pid;// 一定要先创建管道,否则fork出的子进程也会键管道pipe(fd);while((pid = fork()) == -1);// 子进程if(pid == 0){char str[100] = {0};printf("child process: input string:\n");scanf("%s",str);// 写入到管道write(fd[1],str,strlen(str));exit(0);// 父进程}else{wait(0);char buf[30] = {0};// 从管道中读入到bufread(fd[0],buf,30);printf("parent process:\n %s\n",buf);exit(0);}return 0;
}

image-20210930161845872

双通道:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>int main(){// 两个管道int fd1[2],fd2[2];// 创建两个通道pipe(fd1),pipe(fd2);pid_t pid;while((pid = fork()) != -1);// 子进程if(pid == 0){char read_buf1[100] = {0};char write_buf1[100] = {0};printf("child process write:\n")scanf("%s",write_buf1);// 写入write(fd1[1],write_buf1,strlen(write_buf1));// 休眠sleep(10);// 读入read(fd2[0],read_buf1,100);printf("child process read:\n %s\n",read_buf1);exit(0);// 父进程}else{sleep(5);char read_buf2[100] = {0};char write_buf2[100] = {0};read(fd1[0],read_buf2,100);printf("parent process read:\n %s\n",read_buf2);printf("parent process write:\n")scanf("%s",write_buf2);// 写入write(fd2[1],write_buf2,strlen(write_buf2));exit(0);}return 0;
}

image-20210930163940420

实验代码

暂时先不放出来
image-20210930175309031

共享内存

实验预备内容和示例程序

#include<stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>int main(){// 共享内存标识符int shmid;// 创建共享内存if((shmid = shmget((key_t)0x5005,1024,0666|IPC_CREAT)) == -1){printf("shmat(0x5005) failed\n");return -1;}// 用于指向共享内存的指针char *ptext = 0;// 将共享内存连接到当前进程的地址空间,由ptext指向它ptext = (char *)shmat(shmid,0,0);// 操作本程序的ptext指针,就是操作共享内存printf("写入前:%s\n",ptext);sprintf(ptext,"本程序的进程号是:%d",getpid());printf("写入后:%s\n",ptext);// 把共享内存从当前进程中分离shmdt(shmid);// 删除共享内存if(shmctl(shmid,IPC_RMID,0) == -1){printf("shmctl(0x5005) failed\n");return -1;}
}

image-20210930193454327

实验代码

#include<stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>int main(){// 共享内存标识符int shmid;// 创建共享内存if((shmid = shmget((key_t)0x5005,1024,0666|IPC_CREAT)) == -1){printf("shmat(0x5005) failed\n");return -1;}// 用于指向共享内存的指针char *ptext = 0;// 将共享内存连接到当前进程的地址空间,由ptext指向它ptext = (char *)shmat(shmid,0,0);printf("Please enter the name of the contact\n");char name[50];scanf("%s",name);printf("Please enter the contact's phone number\n");long long tel;scanf("%lld",&tel);// 操作本程序的ptext指针,就是操作共享内存// 发送消息到共享内存sprintf(ptext,"联系人: %s\t联系电话: %lld\n",name,tel);// 从共享内存读东西printf("共享内存中读取数据:\n%s\n",ptext);// 把共享内存从当前进程中分离shmdt(ptext);// 删除共享内存if(shmctl(shmid,IPC_RMID,0) == -1){printf("shmctl(0x5005) failed\n");return -1;}
}

image-20211001155436801

消息队列

实验预备内容和示例程序

message.h

#ifndef MESSAGE_H
#define MESSAGE_H
struct mymsgbuf
{long mtype;char mtext[256];
};
#endif

msg_server.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include "message.h"int msqid = -1;// 软终端
void sig_handle(int signo){if(msqid != -1) msgctl(msqid,IPC_RMID,NULL);    // 删除printf("server quit...\n");exit(0);
}int main(){struct mymsgbuf msgbuf;int left,right;char c;int length;if((msqid = msgget(999,0666)) != -1){msgctl(msqid,IPC_RMID,NULL);    // 删除}if((msqid = msgget(999,IPC_CREAT|0666)) == -1 ){printf("error:getmsg\n");exit(1);}signal(SIGINT,sig_handle);      // 注册软中断for(;;){if(msgrcv(msqid,&msgbuf,256,1L,0) == -1){printf("error:msgrcv\n");exit(1);}length = strlen(msgbuf.mtext);left = 0;right = length - 1;while (left < right){c = msgbuf.mtext[left];msgbuf.mtext[left] = msgbuf.mtext[right];msgbuf.mtext[right] = c;left++;right--;}msgbuf.mtext[length] = '\0';msgbuf.mtype = 2;   // 类型改成2if(msgsnd(msqid,&msgbuf,256,0) == -1){printf("error:msgsnd");exit(1);}}msgctl(msqid,IPC_RMID,NULL);exit(0);
}

msg_client.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include "message.h"int main(){struct mymsgbuf msgbuf;int msqid;if((msqid = msgget(999,0666)) == -1){printf("Server is not running\n");exit(1);}printf("Input a line:");scanf("%s",msgbuf.mtext);msgbuf.mtype = 1;if(msgsnd(msqid,&msgbuf,256,0)==-1){printf("error:msgsnd\n");exit(1);}if(msgrcv(msqid,&msgbuf,256,2L,0) == -1){printf("error:msgrcv\n");exit(1);}printf("The reversed line is :%s\n",msgbuf.mtext);exit(0);
}

image-20211004142246959

image-20211004142257587

image-20211004142313369

msgsend.c

#include <stdio.h>
#include <sys/ipc.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>// 消息类型,用枚举
enum MT{MI=1,MD,MS,MSTU,MEMP};
#define QUIT 0
#define MSG_MAX_LEN 1024
#define NAME_LEN 48typedef struct Msg{int msgtype;            //message 的类型char msg[MSG_MAX_LEN];  // message的内容
}Msg;typedef struct Stu{int id;char name[NAME_LEN];int s[3];           // 三门成绩
}Stu;typedef struct Emp
{int id;char name[NAME_LEN];float salary;
}Emp;void menu(void){printf("***消息队列发送测试界面***\n");printf("*** %d.int类型的数据\n",MI);printf("*** %d.double类型的数据\n",MD);printf("*** %d.字符串\n",MS);printf("*** %d.学生信息\n",MSTU);printf("*** %d.员工信息\n",MEMP);printf("*** %d.退出\n",QUIT);printf(">>>");
}size_t readInt(Msg *msg){// 设置消息的类型msg->msgtype = MI;printf("input integer:");// 将消息读入到消息结构体的msg属性中scanf("%d",(int*)msg->msg);return sizeof(int);
}
size_t readDouble(Msg *msg){msg->msgtype = MD;printf("input double:");scanf("%lf",(double*)msg->msg);return sizeof(double);
}
size_t readString(Msg *msg){msg->msgtype = MS;printf("input string:");// 读取换行scanf("%*c");gets(msg->msg);     // gets不安全// 加上\0return strlen(msg->msg)+1;
}
size_t readStu(Msg *msg){msg->msgtype = MSTU;// 强转Stu *pstu = (Stu*)msg->msg;printf("input stu's id:");scanf("%d",&pstu->id);printf("input stu's name:");scanf("%s",pstu->name);printf("input three score:");scanf("%d %d %d",&pstu->s[0],&pstu->s[1],&pstu->s[2]);return sizeof(Stu);
}
size_t readEmp(Msg *msg){msg->msgtype = MEMP;Emp *pe = (Emp*)msg->msg;printf("input emp's id:");scanf("%d",&pe->id);printf("input emp's name:");scanf("%s",pe->name);printf("input emp's salary:");scanf("%f",&pe->salary);return sizeof(Emp);
}int main(){key_t keyid = ftok(".",250);if(keyid == -1){perror("ftok");return -1;}// 创建消息队列int msgid = msgget(keyid,IPC_CREAT|0666);if(msgid == -1){perror("msgget");return -1;}// 创建消息Msg msg = {};bool run = true;size_t msgsz = 0;while(run){menu();int opt = 0;scanf("%d",&opt);switch (opt){case MI:msgsz = readInt(&msg);break;case MD:msgsz = readDouble(&msg);break;case MS:msgsz = readString(&msg);break;case MSTU:msgsz = readStu(&msg);break;case MEMP:msgsz = readEmp(&msg);break;case QUIT:run = false;break;default:printf("error operation!\n");}// msgsz是消息的长度,不包含消息类型的长度int ret = msgsnd(msgid,&msg,msgsz,0);   //0:阻塞 IPC_NOWAIT 不阻塞的if(ret == -1){perror("msgend");run = false;}}return 0;
}

msgrecive.c

#include <stdio.h>
#include <sys/ipc.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>// 消息类型,用枚举
enum MT{MI=1,MD,MS,MSTU,MEMP,FIRST,ABSL};
#define QUIT 0
#define MSG_MAX_LEN 1024
#define NAME_LEN 48typedef struct Msg{int msgtype;            //message 的类型char msg[MSG_MAX_LEN];  // message的内容
}Msg;typedef struct Stu{int id;char name[NAME_LEN];int s[3];           // 三门成绩
}Stu;typedef struct Emp
{int id;char name[NAME_LEN];float salary;
}Emp;void menu(void){printf("***消息队列接受测试界面***\n");printf("*** %d.int类型的数据\n",MI);printf("*** %d.double类型的数据\n",MD);printf("*** %d.字符串\n",MS);printf("*** %d.学生信息\n",MSTU);printf("*** %d.员工信息\n",MEMP);printf("*** %d.接受第一条消息 \n",FIRST);printf("*** %d.接受指定消息小于绝对值最小的消息 \n",ABSL);printf("*** %d.退出\n",QUIT);printf(">>>");
}void showMsg(Msg *msg){switch (msg->msgtype){case MI:printf("recv:%d\n",*(int*)msg->msg);break;case MD:printf("recv:%f\n",*(double*)msg->msg);break;case MS:printf("recv:%s\n",msg->msg);break;case MSTU:{Stu *ps = (Stu *)msg->msg;printf("recv:%d %s %d %d %d\n",ps->id,ps->name,ps->s[0],ps->s[1],ps->s[2]);break;}case MEMP:{Emp *pe = (Emp *)msg->msg;printf("recv:%d %s %f\n",pe->id,pe->name,pe->salary);break;}}
}int main(){key_t keyid = ftok(".",250);if(keyid == -1){perror("ftok");return -1;}// 创建消息队列int msgid = msgget(keyid,IPC_CREAT|0666);if(msgid == -1){perror("msgget");return -1;}// 创建消息Msg msg = {};bool run = true;size_t msgsz = 0;// 读到的消息类型int msgtype = 0;while(run){menu();int opt = 0;scanf("%d",&opt);if(opt >= MI && opt <=MEMP){msgtype = opt;}else if(opt == FIRST){msgtype = 0;}else if(opt == ABSL){printf("input masgtype(<0):");scanf("%d",&msgtype);if(msgtype > 0) msgtype *= -1;}else if(opt == 0){run = false;break;}int ret = msgrcv(msgid,&msg,MSG_MAX_LEN-1,msgtype,IPC_NOWAIT);   if(ret == -1){if(errno == EAGAIN){printf("no this type message");}else{perror("msgend");run = false;}}else{// 显示消息内容showMsg(&msg);}}return 0;
}

实验代码

暂时先不放出来


http://chatgpt.dhexx.cn/article/NyfUaIgs.shtml

相关文章

操作系统实验报告

操作系统 一、实验一 通过 VMware 虚拟机软件安装 Linux二、实验目的三、实验内容&#xff08;实验原理/运用的理论知识、算法/程序流程图、步骤和方法、关键源代码&#xff09;四、实验结果与分析五、小结与心得体会 一、实验二 Windows 进程管理二、实验目的三、实验内容&…

操作系统实验——银行家算法

文章目录 一、实验目的二、实验内容和要求三、实验原理算法实现 四、实验程序代码如下&#xff1a; 五、验证数据和运行结果运行结果截图 六、思考与分析附 一、实验目的 掌握银行家算法思想&#xff0c;并能编程实现。 二、实验内容和要求 1、在Linux环境下编译运行程序&am…

操作系统实验(进程调度)

操作系统实验&#xff08;进程调度&#xff09; 一、实验目的二、实验内容三、实验准备3.1优先权算法3.2时间片轮转调度算法 四、实验 一、实验目的 1.1理解有关进程控制块、进程队列的概念。   1.2掌握进程优先权调度算法和时间片轮转调度算法的处理逻辑。 二、实验内容 2.1…

【MFC】CCriticalSection类在Release编译下调用Lock函数会报0xC0000008错误

【MFC】CCriticalSection类在Release编译下调用Lock函数会报错0xC0000008 问题描述方法一 CRITICAL_SECTION代替CCriticalSection方法二 使用WaitForSingleObject和ReleaseMutex()结语 问题描述 通过以下伪代码方式描述问题&#xff1a; 主对话框类内创建成员变量及结构体变量…

联合使用类CCriticalSection和类CSingleLock同步线程

&#xff08;1&#xff09;新建一个控制台工程SellTicketTest2&#xff0c;并在向导的“应用程序设置”中勾选“MFC”。 &#xff08;2&#xff09;打开SellTicketTest2.cpp&#xff0c;在开头中引入头文件。 #include "afxmt.h"&#xff08;3&#xff09;添加变量&…

单独使用CCriticalSection对象来同步线程

&#xff08;1&#xff09;新建一个控制台工程SellTicketTest&#xff0c;并在向导的“应用程序设置”中勾选“MFC”&#xff0c;因为CCriticalSection属于MFC类&#xff0c;如图所示。 &#xff08;2&#xff09;在SellTicketTest.cpp开头中引入头文件。 #include "afx…

linux查看java线程死锁_ccriticalsection 多线程 死锁_c++ 线程死锁_linux 线程 死锁

qq_407283393122018-12-10 一个很蠢的造成死锁的问题 wanglt3113172018-12-12 什么是死锁&#xff0c;死锁的原因&#xff0c;如何避免 apanying902019-01-09 c3p0连接死锁 Cain_1507662016-09-20 notify产生死锁的场景(备忘) liuchuanyangyan9132017-02-23 C3P0配置错误导致的…

MFC线程同步—— CCriticalSection类使用

多个线程访问临界区时&#xff0c;可以使用临界区对象。临界区对象是一个独占性共享资源&#xff0c;任一时刻只有一个线程可以拥有临界区。拥有临界区的线程可以访问被保护起来的资源或代码段&#xff0c;其他希望进入临界区的线程将被挂起等待&#xff0c;直到拥有临界区的线…

CCriticalSection与CSingleLock

CCriticalSection An object of class CCriticalSection represents a “critical section” — a synchronization object that allows one thread at a time to access a resource or section of code. Critical sections are useful when only one thread at a time can be …

关键部分CCriticalSection使用

类CCriticalSection的对象表示一个“临界区”&#xff0c;它是一个用于同步的对象&#xff0c;同一时刻仅仅同意一个线程存取资源或代码区。临界区在控制一次仅仅有一个线程改动数据或其他的控制资源时很实用。比如&#xff0c;在链表中添加一个结点就仅仅同意一次一个线程进行…

模拟售票大厅实例——多线程时访问共享变量时的安全(CMutex或CCriticalSection的应用)

当程序运行时&#xff0c;可以通过多线程来提高程序运行的效率和拥有更好的体验。但多线程&#xff08;或多进程&#xff09;同时也带来很多的问题&#xff1a;最严重的莫过于对同一个对象或变量访问时&#xff0c;由于线程运行异步的原因&#xff0c;会造成程序运行出现无法控…

在MFC下面实际演示CCriticalSection 的使用

Q&#xff1a;CCriticalSection是什么&#xff1f; A&#xff1a;CCriticalSection是一种线程同步策略 或者说技术 或者方法 总之呢就是这么个意思。。。。 参考资料&#xff1a; http://blog.csdn.net/akof1314/article/details/5773076 http://www.cnblogs.com/hlxs/archi…

Android对话框总结(普通对话框,单选对话框,多选对话框,自定义对话框)

个人推荐: &#x1f4e2;&#x1f4e2;&#x1f4e2; 前些天发现了一个蛮有意思的人工智能学习网站,8个字形容一下 "通俗易懂&#xff0c;风趣幽默"&#xff0c;感觉非常有意思,忍不住分享一下给大家。点击跳转到教程。 一:AlterDialog对话框 二:普通对话框 运行效果…

Android对话框显示输入框

在弹出的对话框显示输入框有两种方法&#xff1a; 法一&#xff1a;新建一个布局&#xff0c;并在对话框中引用它。 法二&#xff1a;直接在Activity中定义Edit并在对话框中用getText方法得到输入信息。

Android对话框的使用

Android对话框的使用 对话框&#xff08;Dialog&#xff09;是Android系统在Activity或者其他组件运行过程中提供的一种提示机制。它可以帮助应用完成一些必要的提示功能&#xff0c;同时提供一些与用户交互的功能。 对话框分为很多种&#xff0c;下面将一一介绍…

android 自定义对话框

// 基础库 implementation com.github.goweii.AnyLayer:anylayer:2.5.0 // 通用弹窗&#xff08;依赖基础库&#xff09; implementation com.github.goweii.AnyLayer:anylayer-common:2.5.0 编写dialog_layout 布局 <?xml version"1.0" encoding"utf-8&qu…

Android对话框的使用总结

一&#xff0e;相关概念 一个对话框一般是一个出现在当前Activity之上的一个小窗口. 处于下面的Activity失去焦点, 对话框接受所有的用户交互. 对话框一般用于提示信息和与当前应用程序直接相关的小功能. Android API 支持下列类型的对话框对象: &#xff08;一&#x…

Android对话框控件读写,Android 对话框控件

对话框控件 一、概述 对话框是 UI 设计中常用的控件&#xff0c;在windows操作系统中&#xff0c;对话框可分为模式对话框和非模式对话框。 模式对话框在使用时&#xff0c;项目中其它UI是不允许操作的&#xff0c;如保存对文件话框 非模式对话框允许操作其它的 UI Android 的对…

Android对话框总结

一、什么是对话框&#xff1f; 一种次要窗口&#xff0c;包含按钮和各种选项&#xff0c;通过它们可以完成特定命令或任务。 查找和替换对话框 对话框与窗口有区别&#xff0c;它没有最大化按钮、没有最小化按钮、大都不能改变形状大小。&#xff08;“打开文件”对话框是可以改…

Android常用对话框

学习目标&#xff1a; 两周入门Android 学习内容&#xff1a; 常见对话框: 对话框是程序与用户交互的一种方式&#xff0c;通常用于显示当前程序提示信息以及相关说明,以小窗口形式展现 普通对话框&#xff1a; 通过AlertDialog.Builder(this).create来创建对话框最后通过…