Linux系统层次结构
调用c库会形成缓存,调用了磁盘。缓冲通常4096大小
进行系统调用时,每次都会调用磁盘。
进程调用
从磁盘中调用到内存中,为其分配磁盘空间。
T1、5个时间函数
1.滴答 clock(void);//启动到调用经过的滴答数
2.秒数时间
time(time_t *t);//标准时间到现在秒数
ctime(time_t *t);//转化为字符串时间
stime(time_t *t);//设置时间
difftime(time_t t1,time_t t2);//计算时间差
3.日历时间
localtime(time_t *t ); //转化为本地时间
gmtime(time_t *t);//转化为格林尼治时间
mktime(struct tm *p);//将UTC转化为time_t
4.微秒时间
gettimeofday(struct timeval *tv);
settimeofday(struct timeval *tv);
5.纳秒时间
clock_gettime(CLOCK_REALTIME, &ts);
对进程的查看流程:
nanosleep(const struct timespec *req, struct timespec *rem);
// 休眠 req 时间,如果被信号中断剩余的时间保存在 rem 中。
1.当前进程执行命令 ./a.out
2.另一个终端查询命令 ps aux|grep "a.out"
3. kill -SIGUSR1 进程ID
IO模型
阻塞IO 如果数据不可用,则函数阻塞 cpu去干别的
非阻塞IO 如果数据可用,则得到数据,否则立即返回。cpu再次调用
IO复用
T2、同步IO与异步IO区别
同步IO为阻塞IO,每个IO会阻塞当前线程的执行。
异步IO为非阻塞IO,当IO完成后系统通知程序,期间不必等待。
同步I/O易于使用,适用于简单的应用程序或对并发性要求不高的场景。异步I/O适用于需要处理大量并发请求、需要高响应性和吞吐量的场景
T3、阻塞型IO与非阻塞IO区别
阻塞型IO若数据未准备就绪无法立即执行IO,调用IO的进程或线程会被阻塞,等待IO完成后的返回结果
非阻塞型IO在无法立即执行的情况下,立刻返回,并给出错误状态码,不会阻塞等待。
IO复用
select() //提供比阻塞型 IO 效率更高的 IO
poll()//可监控的文件数量比 select 更多
epoll()//比 poll 功能更强大,可以监测的文件更多
T4、分别使用 select、poll、epoll 监测标准输入、标准输出描述符,实现将输入的内容输出。
使用 select:
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
int main() {
fd_set read_fds;
struct timeval timeout;
FD_ZERO(&read_fds);
FD_SET(STDIN_FILENO, &read_fds);
while (1) {
timeout.tv_sec = 0;
timeout.tv_usec = 0;
int ready = select(STDIN_FILENO + 1, &read_fds, NULL, NULL, &timeout);
if (ready == -1) {
perror("select");
exit(EXIT_FAILURE);
}
if (FD_ISSET(STDIN_FILENO, &read_fds)) {
char input_data[256];
fgets(input_data, sizeof(input_data), stdin);
printf("Input: %s", input_data);
}
}
return 0;
}
使用 poll:
#include <stdio.h>
#include <stdlib.h>
#include <poll.h>
int main() {
struct pollfd fds[1];
fds[0].fd = STDIN_FILENO;
fds[0].events = POLLIN;
while (1) {
int ready = poll(fds, 1, 0);
if (ready == -1) {
perror("poll");
exit(EXIT_FAILURE);
}
if (fds[0].revents & POLLIN) {
char input_data[256];
fgets(input_data, sizeof(input_data), stdin);
printf("Input: %s", input_data);
}
}
return 0;
}
使用 epoll:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/epoll.h>
int main() {
int epollfd = epoll_create1(0);
if (epollfd == -1) {
perror("epoll_create1");
exit(EXIT_FAILURE);
}
struct epoll_event event;
event.events = EPOLLIN;
event.data.fd = STDIN_FILENO;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, STDIN_FILENO, &event) == -1) {
perror("epoll_ctl");
exit(EXIT_FAILURE);
}
struct epoll_event events[1];
while (1) {
int ready = epoll_wait(epollfd, events, 1, 0);
if (ready == -1) {
perror("epoll_wait");
exit(EXIT_FAILURE);
}
if (events[0].events & EPOLLIN) {
char input_data[256];
fgets(input_data, sizeof(input_data), stdin);
printf("Input: %s", input_data);
}
}
close(epollfd);
return 0;
}
T5、在 day_time.c 模块实现一个设置、获取时间的接口利用 day_time.c 模块接口
写一个 Linux 命令行工具 mydate,用于设置和显示时间.
不能在程序中调用 Linux date命令。用法:
a. 只输入 mydate(),显示当前时间,不能用 asctime ()函数
b. 通过用命令行参数输入输入 mydate 年 月 日 时 分 秒,可以设置当前时间
time+localtime
mktime+stime
#include <time.h>
/* 获取当前时间 */
void get_current_time(struct tm *timeinfo) {
time_t current_time = time(NULL);
localtime_r(¤t_time, timeinfo);
}
/* 设置时间 */
void set_time(struct tm *new_time) {
time_t new_time_t = mktime(new_time);
stime(&new_time_t);
}
#include <stdio.h>
#include <stdlib.h>
#include "day_time.c"
int main(int argc, char *argv[]) {
if (argc == 1) {
/* 只输入mydate,显示当前时间 */
struct tm current_time;
get_current_time(¤t_time);
printf("Current time: %d-%02d-%02d %02d:%02d:%02d\n",
current_time.tm_year + 1900, current_time.tm_mon + 1, current_time.tm_mday,
current_time.tm_hour, current_time.tm_min, current_time.tm_sec);
} else if (argc == 7) {
/* 通过命令行参数设置时间 */
struct tm new_time;
new_time.tm_year = atoi(argv[1]) - 1900;
new_time.tm_mon = atoi(argv[2]) - 1;
new_time.tm_mday = atoi(argv[3]);
new_time.tm_hour = atoi(argv[4]);
new_time.tm_min = atoi(argv[5]);
new_time.tm_sec = atoi(argv[6]);
set_time(&new_time);
printf("Time has been set successfully.\n");
} else {
printf("Invalid arguments.\n");
printf("Usage:\n");
printf(" mydate\n");
printf(" mydate year month day hour minute second\n");
return 1;
}
return 0;
}
T6、进程、线程、程序的区分
进程是程序的一次执行过程,包含了代码、数据和资源;程序是一组指令的集合,用于完成特定任务;线程是进程中的一部分,是执行任务的最小单位,多个线程共享进程的资源。
T7、fork()函数
创建新进程, 通过复制当前进程创建子进程
-
在父进程中,
fork()
函数返回新创建的子进程的进程ID。 -
在子进程中,
fork()
函数返回0。 -
如果创建子进程失败,
fork()
函数返回-1。通过观察返回值来判断这个是啥进程。