文章目录
process和thread的区别
1、进程是最小资源分配单位, 2、线程是最小执行单位, 3、进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。 4、线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
僵尸进程?孤儿进程?守护进程?
僵尸进程:如果一个进程已经终止,但是它的父进程尚未调用 wait 或 waitpid 对它进行清理,这时的进程状态称为僵尸(Zombie)进程。
孤儿进程:父进程先于子进程结束,不是完成子进程回收工作,则子进程成为孤儿进程。init进程将自动变为该进程的父进程。
守护进程:Linux后台运行的一些系统服务进程,没有控制终端,不能直接和用户交互。不受用户登录、注销的影响,一直在运行着。通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。一般采用以d结尾的名字。
进程间通信的方式
管道(pipe)、
fifo,
共享内存、
消息队列、
socket、
信号量
共享内存
read.c
#include<unistd.h>
#include<stdlib.h>
#include<sys/shm.h>
#include<stdio.h>
#define TEXT_SZ 2048
struct share_use_st
{
/* data */
int written;
char text[TEXT_SZ];
};
int main(void)
{
int flat=1;
void *shm=NULL;
struct share_use_st *shared;
int shmid;
//创建一个共享内存对象 UOC_PRIVATE,不同进程需要用KEY
shmid=shmget((key_t)1234,sizeof(struct share_use_st),0777|IPC_CREAT);
if (shmid==-1)
{
/* code */
//出错误处理函数
perror("shmget error");
exit(-1);
}
//挂载内存共享到进程中去,成功返回共享内存的起始位置
shm=shmat(shmid,0,0);
if(shm==(void *)-1)
{
perror("shmat error");
}
shared=(struct share_use_st*)shm;
shared->written==0;
while (flat)
{
/* code */
if (shared->written !=0)
{
/* code */
printf("write text:=%s",shared->text);
sleep(rand()%3);
if(strncmp(shared->text,"end",3)==0)
flat=0;
}
else
{
sleep(1);
}
//卸载共享内存
}
if(shmdt(shm)==-1)
{
perror("shmdt error");
exit(-1);
}
//完成对共享内存的控制,释放内存
if(shmctl(shmid,IPC_RMID,0)==-1)
{
perror("shmctl error");
exit(-1);
}
exit(-1);
return 0;
}
write.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#define TEXT_SZ 2048
struct shared_use_st
{
int written; //作为一个标志,非0:表示可读,0表示可写 1
char text[TEXT_SZ]; //记录写入和读取的文本
};
int main(void)
{
int flat=1;
void *shm=NULL;
struct shared_use_st *shared=NULL;
char buffer[BUFSIZ+1];
int shmid;
shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);
if(shmid==-1)
{
perror("shmget error");
exit(-1);
}
//挂载共享进程放到内存中,成功的话返回共享内存的初始地址
shm=shmat(shmid,(void *)0,0);
if(shm==(void *)-1)
{
perror("shmat error");
exit(-1);
}
printf("Memory attached at %X\n",(int)shm);
shared=(struct shared_use_st *)shm;
while (flat)
{
/* code */
while (shared->written==1)
{
sleep(1);
printf("waiting read\n");
/* code */
}
printf("Enter some text");
fgets(buffer,BUFSIZ,stdin);
strncmpy(shared->written,buffer,TEXT_SZ);
shared->written=1;
if(strncmp(buffer,"end",3)==0)
{
//读到end就结束循环,之间退出
flat=0;
}
}
//卸载共享内存
if(shmdt(shm)==-1)
{
perror("shmdt error");
exit(-1);
}
sleep(2);
exit(-1);
return 0;
}
进程与线程的关系和区别
1、进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
2、线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。
3、进程和线程的关系:
(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
(2)资源分配给进程,同一进程的所有线程共享该进程的所有资源。
(3)处理机分给线程,即真正在处理机上运行的是线程。
(4)线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。
TCP和UDP的区别
TCP和UDP的区别: 1)TCP提供面向连接的传输,通信前要先建立连接(三次握手机制);UDP提供无连接的传输,通信前不需要建立连接。 2)TCP提供可靠的传输(有序,无差错,不丢失,不重复);UDP提供不可靠的传输。 3)TCP面向字节流的传输,因此它能将信息分割成组,并在接收端将其重组;UDP是面向数据报的传输,没有分组开销。 4)TCP提供拥塞控制和流量控制机制;UDP不提供拥塞控制和流量控制机制。
简述OSI 7层模型结构(TCP/IP 4层模型结构)及各层作用
物理层:主要定义物理设备标准 数据链路层:让格式化数据以帧为单位进行传输,错误检查和纠正 网络层:为不同地理位置的网络主机提供连接和路径选择 传输层:定义了一些传输数据的协议和端口号 会话层:通过端口建立数据传输的通路 表示层:确保一个系统的应用层所发送的信息可被另一个系统的应用层读取 应用层:为用户的应用程序提供网络服务 四层:应用层、传输层、网络层、链路层
简述TCP通信的三次握手和四次握手的过程
三次握手 客户端发送一个带SYN标志的TCP报文到服务器。 服务器端回应客户端,同时带ACK标志和SYN标志。 客户再次回应服务器端一个ACK报文。 四次握手 客户端发出带有FIN位的报文,表示关闭连接的请求。 服务器发出带有ACK标志位的报文,应答客户端的关闭连接请求。 服务器发出带有FIN标志位的报文,向客户端发送关闭连接请求。 客户端发出带有ACK标志位的报文,应答服务器的关闭连接请求。
同步和异步的区别?
1、同步,可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是出于阻塞的,只有接收到返回的值或消息后才往下执行其他的命令。
2、异步,执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程,那么当系统接收到返回值或消息时,系统会自动触发委托的异步过程,从而完成一个完整的流程。
3、同步,就是实时处理(如打电话)
4、异步,就是分时处理(如收发短信)
父子进程通过信号通信,实现交替数数。
下面展示一些 内联代码片
。
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
pid_t pid;
void sig_handler_p(int sig) //parent 父进程
{
static int i = 1;
printf("pid = %d, I'm father\t%d\n", getpid(), i);
sleep(1);
i += 2;
kill(pid, SIGUSR1); //为避免竞态条件出现,应该在捕捉函数内完成数数及信号发送.
}
void sig_handler_c(int sig) //child 子进程
{
static int i = 2;
printf("pid = %d, I am child\t%d\n", getpid(), i);
sleep(1);
i += 2;
kill(getppid(), SIGUSR2);
}
int main(void)
{
struct sigaction newact_p, oldact_p; //父进程使用
struct sigaction newact_c, oldact_c; //子进程使用
//子进程响应SIGUSR1
newact_c.sa_handler = sig_handler_c;
sigemptyset(&newact_c.sa_mask);
newact_c.sa_flags = 0;
//注册捕捉信号(捕捉的信号,传入参数新的处理方法,传出参数旧的处理方法)
sigaction(SIGUSR1, &newact_c, &oldact_c);
//父进程响应SIGUSR2
newact_p.sa_handler = sig_handler_p;
sigemptyset(&newact_p.sa_mask);
newact_p.sa_flags = 0;
newact_p.sa_flags |= SA_RESTART;//多加这一行可以将被信号打断的系统调用重启。
sigaction(SIGUSR2, &newact_p, &oldact_p);//注册捕捉信号(捕捉的信号,传入参数新的处理方法,传出参数旧的处理方法)
pid = fork();//此时父子进程都注册了2个信号处理函数,但都只会收到其中一个信号,子进程只收SIGUSR1,父进程只收SIGUSR2
if (pid == 0)
{ //子进程
while (1);
}
else
{ //父进程
raise(SIGUSR2);//自己给自己发信号2
if (wait(NULL))
{ //wait有可能被信号打断。
perror("wait error");
}
//while (1); //或者不使用wait使用这条语句也可以实现。
}
return 0;
}
编程实现多个生产者和多个消费者模型(条件变量)。(3个生产者,5个消费者)
#define PNUM 3//生产者
#define CNUM 5//消费者
// 结构体
struct msg {
int num;
struct msg *next;
}msg;
// 设置两个空节点
struct msg *head;
struct msg *mp;
// 定义一个条件变量变量
pthread_cond_t cond;
// 定义一个互斥锁变量
pthread_mutex_t lock;
void *consumer(void *num)//消费者
{
while(1) {
pthread_mutex_lock(&lock); //加锁
while(head == NULL) {
pthread_cond_wait(&cond, &lock); //判断是否存在节点,如果存在节点,抢到节点的处理,没有抢到的继续阻塞等待
}
mp = head; //删除节点
head = mp->next;
printf("----Consume %d ----%d\n",(int)num, mp->num);
free(mp);
pthread_mutex_unlock(&lock); //解锁
sleep(rand() % 3);
}
}
void *producer(void *num)//生产者
{
while(1) {
pthread_mutex_lock(&lock);
mp = malloc(sizeof(struct msg)); //创建一个新的节点
mp->num = rand() % 1000 + 1;
printf("****Producer %d****%d\n",(int)num, mp->num);
mp->next = head; //插入链表
head = mp;
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond); //给消费者发送信号
sleep(rand() %5);
}
}
int main(void)
{
pthread_t pid[PNUM],cid[CNUM];
int i = 0;
srand(time(NULL)); //创建3个生产者和5个消费者
for(i = 0; i < PNUM; i++) {
pthread_create(&pid[i],NULL,producer,(void *)i);
}
for(i = 0; i < CNUM; i++) {
pthread_create(&cid[i], NULL, consumer, (void *)i);
}
for(i = 0; i < PNUM; i++) { //回收线程资源
pthread_join(pid[i], NULL);
}
for(i = 0; i < CNUM; i++) {
pthread_join(cid[i], NULL);
}
return 0;
}
编写一个能判断客户端发送的字符串是否是回文的服务器程序 (函数的接口为 int isHuiWen (char *str))
#define PNUM 3//生产者
#define CNUM 5//消费者
// 结构体
struct msg {
int num;
struct msg *next;
}msg;
// 设置两个空节点
struct msg *head;
struct msg *mp;
// 定义一个条件变量变量
pthread_cond_t cond;
// 定义一个互斥锁变量
pthread_mutex_t lock;
void *consumer(void *num)//消费者
{
while(1) {
pthread_mutex_lock(&lock); //加锁
while(head == NULL) {
pthread_cond_wait(&cond, &lock); //判断是否存在节点,如果存在节点,抢到节点的处理,没有抢到的继续阻塞等待
}
mp = head; //删除节点
head = mp->next;
printf("----Consume %d ----%d\n",(int)num, mp->num);
free(mp);
pthread_mutex_unlock(&lock); //解锁
sleep(rand() % 3);
}
}
void *producer(void *num)//生产者
{
while(1) {
pthread_mutex_lock(&lock);
mp = malloc(sizeof(struct msg)); //创建一个新的节点
mp->num = rand() % 1000 + 1;
printf("****Producer %d****%d\n",(int)num, mp->num);
mp->next = head; //插入链表
head = mp;
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond); //给消费者发送信号
sleep(rand() %5);
}
}
int main(void)
{
pthread_t pid[PNUM],cid[CNUM];
int i = 0;
srand(time(NULL)); //创建3个生产者和5个消费者
for(i = 0; i < PNUM; i++) {
pthread_create(&pid[i],NULL,producer,(void *)i);
}
for(i = 0; i < CNUM; i++) {
pthread_create(&cid[i], NULL, consumer, (void *)i);
}
for(i = 0; i < PNUM; i++) { //回收线程资源
pthread_join(pid[i], NULL);
}
for(i = 0; i < CNUM; i++) {
pthread_join(cid[i], NULL);
}
return 0;
}