一、linux杀死共享内存
查看共享内存命令:ipcs -m
删除共享内存命令:ipcrm <shmid>
二、tcp慢启动
发送方维持一个拥塞窗口 cwnd ( congestion window )的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞。
发送方控制拥塞窗口的原则是:只要网络没有出现拥塞,拥塞窗口就再增大一些,以便把更多的分组发送出去。但只要网络出现拥塞,拥塞窗口就减小一些,以减少注入到网络中的分组数。
慢开始算法:当主机开始发送数据时,如果立即所大量数据字节注入到网络,那么就有可能引起网络拥塞,因为现在并不清楚网络的负荷情况。因此,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是说,由小到大逐渐增大拥塞窗口数值。通常在刚刚开始发送报文段时,先把拥塞窗口 cwnd 设置为一个最大报文段MSS的数值。而在每收到一个对新的报文段的确认后,把拥塞窗口增加至多一个MSS的数值。用这样的方法逐步增大发送方的拥塞窗口 cwnd ,可以使分组注入到网络的速率更加合理。
三、exit 跟_exit的区别
1、exit会关闭所有为关闭的文件描述符。_exit应该也会。
2、exit()和_exit()这两个函数都是用于函数退出,但这两者有一些细微的差别,在exit()函数里会调用_exit()函数。下面来看看exit()的函数代码大概:
void exit(int status)
{
while(_exit_funcs != NULL)
{
_exit_funcs = _exit_funcs->next;
}
_exit(status);
}
其中_exit_funcs是存储由__cxa_atexit和atexit注册的函数的链表,而这个while循环则遍历该链表并逐个调用这些注册的函数。最后再调用_exit(),这个函数的作用仅仅是调用了exit这个系统调用。即_exit()调用后,进程会直接结束。
所以exit()和_exit()的区别在于,exit()会首先将所有使用atexit注册的函数进行调用以后再推出,而_exit()则是直接结束程序。
注意:_cxa_atexit()和atexit()这两个函数的作用相同,可以看成等价。这两个函数的作用是注册一些函数用于在main()函数调用完以后再调用。
#include
#include <stdlib.h>
void test1()
{
printf("hello, test1.\n");
}
void test2()
{
printf("hello, test2.\n");
}
void test3()
{
printf("hello, test3.\n");
}
void test4()
{
printf("hello, test4.\n");
}
void test5()
{
printf("hello, test5.\n");
}
int main()
{
atexit(test1);
atexit(test2);
atexit(test3);
atexit(test4);
atexit(test5);
printf("hello, main.\n");
return 0;
}
运行结果:
(1)使用exit()函数后
#include <stdio.h>
#include <stdlib.h>
void test1()
{
printf("hello, test1.\n");
}
void test2()
{
printf("hello, test2.\n");
}
void test3()
{
printf("hello, test3.\n");
}
void test4()
{
printf("hello, test4.\n");
}
void test5()
{
printf("hello, test5.\n");
exit(0);
}
int main()
{
atexit(test1);
atexit(test2);
atexit(test3);
atexit(test4);
atexit(test5);
printf("hello, main.\n");
return 0;
}
运行结果:
(2)使用_exit()函数
#include <stdio.h>
#include <stdlib.h>
void test1()
{
printf("hello, test1.\n");
}
void test2()
{
printf("hello, test2.\n");
}
void test3()
{
printf("hello, test3.\n");
}
void test4()
{
printf("hello, test4.\n");
}
void test5()
{
printf("hello, test5.\n");
_exit(0);
}
int main()
{
atexit(test1);
atexit(test2);
atexit(test3);
atexit(test4);
atexit(test5);
printf("hello, main.\n");
return 0;
}
四、僵尸进程可以kill杀死吗
僵尸进程用kill命令是无法杀掉的,但是我们可以结果掉僵尸进程的爸爸,
僵尸daddy挂了之后,僵尸进程就成了孤儿进程,孤儿进程不会占用系统资源,
会被init进程**(init process (PID 1))**收养,
然后init进程(init process (PID 1))将其回收。
五、线程安全跟可重入的区别
可重入函数是线程安全的真子集:https://blog.csdn.net/ypt523/article/details/80380272
(1)线程安全不一定是可重入的,而可重入函数一定是线程安全的。
(2)线程安全是多个线程下引起的,但可重入函数可以在只有一个线程的情况下发生。
(3)若一个函数中存在全局变量,那么这个函数既不是线程安全的也不是可重入的。
(4)线程安全函数能够使不同的线程访问同一块地址空间,而可重入函数要求不同的执行流对数据的操作互不影响结果是相同的。
六、epollwait可以多线程吗
多线程epoll_wait后得到的活跃fd是线程安全的吗?
或者说多个线程在epoll_wait后,各个线程得到的epoll_event[]里的socket有相同的吗?
有可能各个线程得到的epoll_event[]里的socket有相同的。特别在LT模式下。虽然内核使用了排他锁每次只唤醒一个epoll_wait()进程,但如果在LT模式下,而且唤醒的进程没有处理完该fd的全部数据,那么下一个epoll_wait()进程醒来的时候,就有可能得到该fd还是可读的,这样各个线程得到的epoll_event[]里的socket就有可能是相同的。注意是:可能!!!
加上EPOLLONESHOT ,一个socket就只有一个thread处理,然后再epoll_ctl EPOLL_CTL_MOD修改该fd。
正解,EPOLLONESHOT,
至于ET和LT我还没有进行过对比,但是在大量实践中,LT+EPOLLONESHOT的工作是可靠的。
网友评论