进程创建
进程
进程在执行过程中可能创建多个新的进程。创建进程称为父进程,而新的进程称为子进程。每个新进程可以再创建其他进程,从而形成进程树。
大多数的操作系统(包括 UNIX、Linux 和 Windows)对进程的识别采用的是唯一的进程标识符(pid),pid 通常是一个整数值。系统内的每个进程都有一个唯一 pid,它可以用作索引,以便访问内核中的进程的各种属性。
链接:服务器并发
首先:accept,read,write可能会阻塞。
多线程实现或者多进程可以实现
其次:IO多路转接+多线程实现(IO多路复用不考虑)
创建父线程accept
创建子线程read,write(线程同步可能需要,为了共享使用资源)
链接:进程的创建和终止(超详细)
链接:创建进程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
struct SockInfo
{
int fd; // 通信
pthread_t tid; // 线程ID
struct sockaddr_in addr; // 地址信息
};
struct SockInfo infos[128];
void* working(void* arg)
{
while(1)
{
struct SockInfo* info = (struct SockInfo*)arg;
// 接收数据
char buf[1024];
int ret = read(info->fd, buf, sizeof(buf));
if(ret == 0)
{
printf("客户端已经关闭连接...\n");
info->fd = -1;
break;
}
else if(ret == -1)
{
printf("接收数据失败...\n");
info->fd = -1;
break;
}
else
{
write(info->fd, buf, strlen(buf)+1);
}
}
return NULL;
}
int main()
{
// 1. 创建用于监听的套接字
int fd = socket(AF_INET, SOCK_STREAM, 0);
if(fd == -1)
{
perror("socket");
exit(0);
}
// 2. 绑定
struct sockaddr_in addr;
addr.sin_family = AF_INET; // ipv4
addr.sin_port = htons(8989); // 字节序应该是网络字节序
addr.sin_addr.s_addr = INADDR_ANY; // == 0, 获取IP的操作交给了内核
int ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
if(ret == -1)
{
perror("bind");
exit(0);
}
// 3.设置监听
ret = listen(fd, 100);
if(ret == -1)
{
perror("listen");
exit(0);
}
// 4. 等待, 接受连接请求
int len = sizeof(struct sockaddr);
// 数据初始化
int max = sizeof(infos) / sizeof(infos[0]);
for(int i=0; i<max; ++i)
{
bzero(&infos[i], sizeof(infos[i]));
infos[i].fd = -1;
infos[i].tid = -1;
}
// 父进程监听, 子进程通信
while(1)
{
// 创建子线程
struct SockInfo* pinfo;
for(int i=0; i<max; ++i)
{
if(infos[i].fd == -1)
{
pinfo = &infos[i];
break;
}
if(i == max-1)
{
sleep(1);
i--;
}
}
int connfd = accept(fd, (struct sockaddr*)&pinfo->addr, &len);
printf("parent thread, connfd: %d\n", connfd);
if(connfd == -1)
{
perror("accept");
exit(0);
}
pinfo->fd = connfd;
pthread_create(&pinfo->tid, NULL, working, pinfo);
pthread_detach(pinfo->tid);
}
// 释放资源
close(fd); // 监听
return 0;
}
借鉴一下,客户端代码耶
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <winsock2.h>
typedef int socklen_t;
#define MAX 1024
const int PORT = 9010;
int fd;
char buffer[MAX];
struct BuffterInfo{
int flag; //状态
pthread_t tid; //线程id
int cbn; //任务编号
};
struct BuffterInfo infos[MAX];
//判断并发送指令
int Judge(char buffer[],int runfg){
//判断
if (strcmp(buffer, "001") == 0)
{
printf("running...\n");
//运行指令不可重复
if(runfg==1)
{
return runfg=-1;
}
runfg=1;
} else if (strcmp(buffer, "002") == 0) {
printf("stop\n");
//停止指令不可重复
if(runfg==0){
return runfg=-1;
}
runfg=0;
}
return runfg;
}
void* working(void* arg)
{
//struct BuffterInfo* info = (struct BuffterInfo*)arg;
//接受
while(1){
char buf[MAX];
memset(buf, 0, MAX);
int ret =recv(fd, buf, MAX, 0);
if(ret >0){
printf("%s", buf);
memset(buf, 0, strlen(buf));
}else if(ret<0){
perror("read from socket");
break;
}else if(!ret){
write(fd, buf, strlen(buf)+1);
break;
}
memset(buf, 0, strlen(buf));
printf(" %s ", buf);
}
printf ("输出\n");
return NULL;
}
int main() {
WSADATA ws;
WSAStartup(MAKEWORD(2, 2), &ws);
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("192.168.64.129");
serv_addr.sin_port = htons(PORT);
// 创立套接字
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(0);
};
// 建立连接
if (connect(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("connect error");
exit(0);
}
//数据初始化
memset(buffer, 0, MAX);
int runfg = 0;
int max=sizeof(infos)/sizeof(infos[0]);
for(int i=0;i<max;i++){
memset(&infos[i],0,sizeof(infos[i]));
infos[i].flag = 0;
infos[i].tid=-1;
infos[i].cbn = -1;
}
// 通信
while (1) {
printf("input: \n");
scanf("%s",buffer);
getchar();
printf ("flag%d\n",runfg);
runfg=Judge(buffer,runfg);
if(runfg==-1){
printf("command repeats!\n");
memset(buffer, 0, MAX);
continue;
}
//发送
if (send(fd, buffer, strlen(buffer), 0) == -1) {
perror("send");
}
printf ("发送%s\n",buffer);
if( strcmp(buffer, "002") == 0){
for(int i=0; i<max; i++){
if(infos[i].cbn==1){
pthread_exit(infos[i]->tid);
infos[i].tid = -1;
printf("had cancel the thread!\n");
}
}
continue;
}
memset(buffer, 0, MAX);
printf ("创建%d\n",runfg);
//子线程创建
struct BuffterInfo* pinfo;
for(int i=0; i<max; ++i){
if(infos[i].tid == -1){
pinfo = &infos[i];
break;
}
if(i == max-1){
sleep(1);
i--;
}
}
pinfo->cbn = 1; //targetApp.c 为编号1
pinfo->flag = runfg;
//一个事件的输出当做进程
pthread_create(&pinfo->tid,NULL,working,NULL);
pthread_detach(pinfo->tid);
}
system("pause");
return 0;
}
单线程互斥锁
使用两个变量:互斥量和条件变量;初始化,暂停和恢复进程
链接1:有关pthread线程的暂停与恢复的讨论
int main()
{
pthread_t id;
int ret;
ret = pthread_create(&id,NULL,threadFunc,(void *)sockClient);
if (ret != 0)
{
printf("Create thread error!\r\n");
exit(1);
}
pthread_create(&thread, NULL, threadFunc, NULL);
while (1)
{
if( kbhit() )//有键盘输入 kbhit !0;
{
ch = getch();
if( ch == 's' )
{
pthread_suspend();
}
if(ch == 'r')
{
pthread_resume();
}
}
}
return 0;
}
#include <unistd.h>
#include <pthread.h>
static pthread_mutex_t mutex;
static pthread_cond_t cond;
static int flag = 0;
void srpthread_init()
{
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
}
void srpthread_suspend()
{
pthread_mutex_lock(&mutex);
flag--;
pthread_mutex_unlock(&mutex);
}
void srpthread_resume()
{
pthread_mutex_lock(&mutex);
flag++;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
void *thread_run()
{
while(1)
{
pthread_mutex_lock(&mutex);
while(flag<=0)
{
pthread_cond_wait(&cond,&mutex);
}
pthread_mutex_unlock(&mutex);
//actual work
printf("i am running!\n");
}
}
int main(int argc,char *argv[])
{
char ch;
pthread_t p1;
srpthread_init();
pthread_create(&p1,NULL,(void *)thread_run,NULL);
while(1)
{
scanf("%c",&ch);
switch(ch)
{
case 's':
srpthread_suspend();
break;
case 'r':
srpthread_resume();
break;
default:
break;
}
}
#if 0
printf("1111\n");
srpthread_resume();
printf("2222\n");
sleep(3);
printf("3333\n");
srpthread_suspend();
printf("4444\n");
#endif
return 1;
}
结合起来!客户端代码简易实现,优化!优化!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <winsock2.h>
typedef int socklen_t;
#define MAX 1024
const int PORT = 9010;
int fd;
char buffer[MAX];
static pthread_mutex_t mutex; //互斥量
static pthread_cond_t cond; //条件变化
static int flag = 0;
//初始化锁
void pthread_init()
{
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
}
//暂停
void pthread_suspend()
{
pthread_mutex_lock(&mutex);
flag--;
pthread_mutex_unlock(&mutex);
}
//恢复
void pthread_resume()
{
pthread_mutex_lock(&mutex);
flag++;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
//判断并发送指令
int Judge(char buffer[],int runfg){
//判断
if (strcmp(buffer, "001") == 0)
{
printf("running...\n");
//运行指令不可重复
if(runfg==1)
{
return runfg=-1;
}
runfg=1;
} else if (strcmp(buffer, "002") == 0) {
printf("stop\n");
//停止指令不可重复
if(runfg==0){
return runfg=-1;
}
runfg=0;
}
return runfg;
}
void* working(void* arg)
{
//struct BuffterInfo* info = (struct BuffterInfo*)arg;
//接受
while(1){
char buf[MAX];
memset(buf, 0, MAX);
int ret =recv(fd, buf, MAX, 0);
if(ret >0){
printf("%s", buf);
}else if(ret<0){
perror("read from socket");
break;
}else if(!ret){
break;
}
memset(buf, 0, strlen(buf));
}
printf ("输出\n");
return NULL;
}
int main() {
WSADATA ws;
WSAStartup(MAKEWORD(2, 2), &ws);
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("192.168.64.129");
serv_addr.sin_port = htons(PORT);
// 创立套接字
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(0);
};
// 建立连接
if (connect(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("connect error");
exit(0);
}
printf ("connect\n");
//数据初始化
memset(buffer, 0, MAX);
int runfg = 0;
//子线程创建
pthread_t tid;
pthread_init();
pthread_create(&tid,NULL,working,NULL);
pthread_resume();
// printf ("makepthread\n");
// 通信
while (1) {
printf("input: \n");
scanf("%s",buffer);
getchar();
printf ("flag=%d\n",runfg);
//指令不能重复
runfg=Judge(buffer,runfg);
if(runfg==-1){
printf("command repeats!\n");
memset(buffer, 0, MAX);
continue;
}
//发送
if (send(fd, buffer, strlen(buffer), 0) == -1) {
perror("send");
}
printf ("发送%s\n",buffer);
//001接受收,002停止接收,接收值的变化由服务器决定
if( strcmp(buffer, "002") == 0){
pthread_suspend();
printf("had suspend the thread!\n");
}else if (strcmp(buffer,"001")==0){
pthread_resume();
}
memset(buffer, 0, MAX);
printf ("创建%d\n",runfg);
}
system("pause");
return 0;
}