Linux系统编程

本文介绍了操作系统的核心概念,包括内核、系统调用、进程和虚拟内存的作用。同时,讨论了并发的概念和fork进程的示例,以及在Linux中如何通过文件描述符管理文件。此外,还探讨了生产者/消费者模型在多线程环境中的实现,利用互斥锁和条件变量保证同步。最后,文章提到了epoll作为高效网络I/O多路复用技术在服务器端的应用。
摘要由CSDN通过智能技术生成

基本概念:

操作系统

出现原因:为解决程序员掌握计算机系统硬件细节而为计算机安装的一层软件

作用:为用户提供可视化计算机硬件模型、提供计算机硬件接口,管理硬件资源

内核

地位:是操作系统中最重要的核心程序

作用:管理计算机硬件,分配内存资源

系统调用

出现原因:防止程序间运行冲突,用户只在用户态条件下运行

作用:内核的入口,进入内核,通过内核访问硬件

进程

定义:程序运行中需要分配资源,需要对进程进行资源管理

作用:是操作系统进行资源分配和调度的基本单位

虚拟内存

定义:内核为进程分配一虚拟内存,后经操作系统翻译后分配到真实物理内存中,这种内存分配方式成为虚拟内存

作用:防止程序间内存分配冲突和运行冲突

并发

定义:CPU在经历多个进程时会先执行一个程序,在等待程序运行完毕期间会执行另一个程序,当第一个进程结束时会返回到该结束进程中,这种操作叫做并发,宏观上是一个时间段内运行了多个程序,但在微观内是CPU在一个时间段内只运行一个程序

文件描述符

Linux中打开/创建文件会从操作系统中返回一个int值,被称为文件描述符,通常是非负整数,在一个进程启动后,会默认打开三个文件描述符,分别是0(标准输入)1(标准输出)2(标准错误)

通过open打开或创建文件时会得到一个在文件描述表中未使用的最小的文件描述符

———————————————————————————————————————————

进程1 fork() [1]  && //父进程

进程2 fork() [0] && //子进程 ->短路 结束

进程3 fork() [1]  && fork() [1]  // &&右侧fork() [1] ->fork() [0] 结束

进程4 fork() [1]  && fork() [1] --> 1 && 1 执行函数体内容,fork(1) -> fork(0) 结束

一共有四个进程,打印四个end

———————————————————————————————————————————

进程1 fork() [1] //父进程 -> 1 || (短路) -> if(1) > //执行函数体

进程2 fork() [1]  -> fork() [0] 结束

进程3 fork() [0] //子进程 因为父进程为1 ,所以 0 || 1,fork() [0] || fork() [1]

进程4 fork() [1] -> fork() [0] 结束

进程5 因为0 || 1 执行函数体内容 fork(1) -> fork(0) 结束

一共有五个进程,打印五个end\n

———————————————————————————————————————————

进程1 fork() [1] 1 || X短路,if(1) ->//进入函数体 fork() [1] -> fork() [0]

进程2 短路后0 || 1 -> fork() [0] || fork() [1]

进程3 进程2 || 右侧fork() [1] -> fork() [0] 结束

进程4 进程1 fork() [1] -> fork() [0]结束

进程5 ,进程2 || 右侧fork() [1] -> fork() [0]结束

进程6 if(1 && 1) 进入函数体 fork() [1] -> fork() [0]结束

一共六个进程,打印六个end\n

 ——————————————————————————————————————————

生产者 / 消费者模型 (条件变量 / 互斥量)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>           
#include<unistd.h>
#include<errno.h>
#include<pthread.h>
#include<fcntl.h>
#include<time.h>

pthread_mutex_t mutex;//互斥锁
pthread_cond_t cond;//条件变量
//初始化链表
struct Node{
	int number;//数据域
	struct Node* next;//指针域
};

struct Node* head;//创建头节点

struct Node* append_node(int number){//添加节点
	struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
	new_node->number = number;
	new_node->next = head;
	head = new_node;
	return head;
}

int pop_head_node(){
	struct Node* temp = head;
	int number = temp->number;
	head = head->next;
	free(temp);
	return number;
}

void* producer(void* args)
{
	while(1)
	{
		pthread_mutex_lock(&mutex);
		append_node(rand() % 500 + 1);
		pthread_cond_signal(&cond);
		pthread_mutex_unlock(&mutex);
		sleep(1);
	}
}

void* consumer(void* args)
{
	while(1)
	{
		pthread_mutex_lock(&mutex);
		while(head == NULL)
		{
			pthread_cond_wait(&cond,&mutex);
		}
		printf("Number = %d\n",pop_head_node());
		pthread_mutex_unlock(&mutex);
	}
}

int main(int argc, char* argv[])
{
    srand(time(NULL));//种随机种子
	
	pthread_t tid1;//创建tid2 tid2线程编号
	pthread_t tid2;

	pthread_create(&tid1,NULL,producer,NULL);//创建线程
	pthread_create(&tid2,NULL,consumer,NULL);

	pthread_join(tid1,NULL);//返回值
	pthread_join(tid2,NULL);

    return 0;

}

epoll

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <pthread.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/epoll.h>

#define SERVER_PORT 8000
#define BUFFER_SIZE 1024
#define EVENT_SIZE 1024

int main(int argc, char* argv[]){
    int lfd = socket(AF_INET,SOCK_STREAM,0); //创建套接字
    if(lfd == -1){
        perror("socket error");
        exit(1);
    }
    
    struct sockaddr_in serveraddr,clientaddr;
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(SERVER_PORT);
    serveraddr.sin_addr.s_addr = INADDR_ANY;

    int ret = bind(lfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
    if(ret == -1){
        perror("bind error");
        exit(1);
    }

    ret = listen(lfd,64);
    if(ret == -1){
        perror("listen error");
        exit(1);
    }
    socklen_t addr_len = sizeof(clientaddr);
    int cfd = -1;
    char buf[BUFFER_SIZE];
    int read_ret = 0;
    char clientip[32];
    int epoll_ret = 0;
    int epfd = epoll_create(64); //创建epoll对象
    struct epoll_event event;    //创建结构体对象
    struct epoll_event events[EVENT_SIZE];  //创建结构体数组
    event.events = EPOLLIN;  //设置监听事件为读事件
    event.data.fd = lfd;     //设置监听文件描述符
    epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&event);  //将lfd增加到epoll对象里
    while(1){
        epoll_ret = epoll_wait(epfd,events,EVENT_SIZE,0);
        if(epoll_ret < 0){
            perror("epoll error");
            exit(1);
        }
        else if(epoll_ret == 0){

        }
        else{
            for(int i = 0; i < epoll_ret;i++){
                int fd = events[i].data.fd;
                if(events[i].events & EPOLLIN){
                    if(fd == lfd){ //判断是否是通信套接字
                        cfd = accept(lfd,(struct sockaddr*)&clientaddr,&addr_len);
                        printf("有新的客户端建立连接:IP=%s, PORT=%d\n",inet_ntop(AF_INET,&clientaddr.sin_addr.s_addr,clientip,sizeof(clientip)),ntohs(clientaddr.sin_port));
                        if(cfd < 0){
                            perror("accept error");
                            exit(1);
                        }
                        else{
                            event.events = EPOLLIN;
                            event.data.fd = cfd;
                            epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&event);
                        }
                    }
                    else{ //客户端套接字
                        read_ret = read(fd,buf,BUFFER_SIZE);
                        if(read_ret < 0){
                            perror("read error");
                            exit(1);
                        }
                        else if(read_ret == 0){
                            printf("客户端断开连接\n");
                            epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL);
                            close(fd);
                        }
                        else{
                            write(STDOUT_FILENO,buf,read_ret);
                            write(fd,buf,read_ret);
                        }
                    }
                }
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值