首页 > 系统相关 >Linux usb【3】- gadget驱动介绍

Linux usb【3】- gadget驱动介绍

时间:2025-01-22 18:58:12浏览次数:3  
标签:dwc3 usb udc gadget ret dwc Linux

本文基于新思的dwc3 usb控制器,介绍usb的gadget驱动,kernel版本为5.15。

probe刚开始和前面介绍的host驱动是一样的,只不过在dwc3_core_init_mode函数中会选择gadget初始化dwc3_gadget_init。

1214  static int dwc3_core_init_mode(struct dwc3 *dwc)
1215  {
1216  	struct device *dev = dwc->dev;
1217  	int ret;
1218  
1219  	switch (dwc->dr_mode) {
1220  	case USB_DR_MODE_PERIPHERAL:
1221  		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);
1222  
1223  		if (dwc->usb2_phy)
1224  			otg_set_vbus(dwc->usb2_phy->otg, false);
1225  		phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);
1226  		phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE);
1227  
1228  		ret = dwc3_gadget_init(dwc);
1229  		if (ret)
1230  			return dev_err_probe(dev, ret, "failed to initialize gadget\n");
1231  		break;
1232  	case USB_DR_MODE_HOST:
1233  		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST);
1234  
1235  		if (dwc->usb2_phy)
1236  			otg_set_vbus(dwc->usb2_phy->otg, true);
1237  		phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
1238  		phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST);
1239  
1240  		ret = dwc3_host_init(dwc);
1241  		if (ret)
1242  			return dev_err_probe(dev, ret, "failed to initialize host\n");
1243  		break;
1244  	case USB_DR_MODE_OTG:
1245  		INIT_WORK(&dwc->drd_work, __dwc3_set_mode);
1246  		ret = dwc3_drd_init(dwc);
1247  		if (ret)
1248  			return dev_err_probe(dev, ret, "failed to initialize dual-role\n");
1249  		break;
1250  	default:
1251  		dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);
1252  		return -EINVAL;
1253  	}
1254  
1255  	return 0;
1256  }

在dwc3_gadget_init中主要就是调用dwc3_gadget_init_endpoints初始化ep, 并且申请了usb_gadget数据结构,并初始化里面的usb_gadget_ops回调函数, 然后调用usb_add_gadget。

4303  /**
4304   * dwc3_gadget_init - initializes gadget related registers
4305   * @dwc: pointer to our controller context structure
4306   *
4307   * Returns 0 on success otherwise negative errno.
4308   */
4309  int dwc3_gadget_init(struct dwc3 *dwc)
4310  {
4311  	int ret;
4312  	int irq;
4313  	struct device *dev;
4314  
4315  #ifdef CONFIG_USB_DWC3_AXERA
4316  	axera_usb_device_init(dwc);
4317  #endif
4318  
4319  	irq = dwc3_gadget_get_irq(dwc);
4320  	if (irq < 0) {
4321  		ret = irq;
4322  		goto err0;
4323  	}
4324  
4325  	dwc->irq_gadget = irq;
4326  
4327  	dwc->ep0_trb = dma_alloc_coherent(dwc->sysdev,
4328  					  sizeof(*dwc->ep0_trb) * 2,
4329  					  &dwc->ep0_trb_addr, GFP_KERNEL);
4330  	if (!dwc->ep0_trb) {
4331  		dev_err(dwc->dev, "failed to allocate ep0 trb\n");
4332  		ret = -ENOMEM;
4333  		goto err0;
4334  	}
4335  
4336  	dwc->setup_buf = kzalloc(DWC3_EP0_SETUP_SIZE, GFP_KERNEL);
4337  	if (!dwc->setup_buf) {
4338  		ret = -ENOMEM;
4339  		goto err1;
4340  	}
4341  
4342  	dwc->bounce = dma_alloc_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE,
4343  			&dwc->bounce_addr, GFP_KERNEL);
4344  	if (!dwc->bounce) {
4345  		ret = -ENOMEM;
4346  		goto err2;
4347  	}
4348  
4349  	init_completion(&dwc->ep0_in_setup);
4350  	dwc->gadget = kzalloc(sizeof(struct usb_gadget), GFP_KERNEL);
4351  	if (!dwc->gadget) {
4352  		ret = -ENOMEM;
4353  		goto err3;
4354  	}
4355  
4356  
4357  	usb_initialize_gadget(dwc->dev, dwc->gadget, dwc_gadget_release);
4358  	dev				= &dwc->gadget->dev;
4359  	dev->platform_data		= dwc;
4360  	dwc->gadget->ops		= &dwc3_gadget_ops;
4361  	dwc->gadget->speed		= USB_SPEED_UNKNOWN;
4362  	dwc->gadget->ssp_rate		= USB_SSP_GEN_UNKNOWN;
4363  	dwc->gadget->sg_supported	= false;
4364  	dwc->gadget->name		= "dwc3-gadget";
4365  	dwc->gadget->lpm_capable	= !dwc->usb2_gadget_lpm_disable;
4366  
4367  	/*
4368  	 * FIXME We might be setting max_speed to <SUPER, however versions
4369  	 * <2.20a of dwc3 have an issue with metastability (documented
4370  	 * elsewhere in this driver) which tells us we can't set max speed to
4371  	 * anything lower than SUPER.
4372  	 *
4373  	 * Because gadget.max_speed is only used by composite.c and function
4374  	 * drivers (i.e. it won't go into dwc3's registers) we are allowing this
4375  	 * to happen so we avoid sending SuperSpeed Capability descriptor
4376  	 * together with our BOS descriptor as that could confuse host into
4377  	 * thinking we can handle super speed.
4378  	 *
4379  	 * Note that, in fact, we won't even support GetBOS requests when speed
4380  	 * is less than super speed because we don't have means, yet, to tell
4381  	 * composite.c that we are USB 2.0 + LPM ECN.
4382  	 */
4383  	if (DWC3_VER_IS_PRIOR(DWC3, 220A) &&
4384  	    !dwc->dis_metastability_quirk)
4385  		dev_info(dwc->dev, "changing max_speed on rev %08x\n",
4386  				dwc->revision);
4387  
4388  	dwc->gadget->max_speed		= dwc->maximum_speed;
4389  	dwc->gadget->max_ssp_rate	= dwc->max_ssp_rate;
4390  
4391  	/*
4392  	 * REVISIT: Here we should clear all pending IRQs to be
4393  	 * sure we're starting from a well known location.
4394  	 */
4395  
4396  	ret = dwc3_gadget_init_endpoints(dwc, dwc->num_eps);
4397  	if (ret)
4398  		goto err4;
4399  
4400  	ret = usb_add_gadget(dwc->gadget);
4401  	if (ret) {
4402  		dev_err(dwc->dev, "failed to add gadget\n");
4403  		goto err5;
4404  	}
4405  
4406  	if (DWC3_IP_IS(DWC32) && dwc->maximum_speed == USB_SPEED_SUPER_PLUS)
4407  		dwc3_gadget_set_ssp_rate(dwc->gadget, dwc->max_ssp_rate);
4408  	else
4409  		dwc3_gadget_set_speed(dwc->gadget, dwc->maximum_speed);
4410  
4411  	return 0;
4412  
4413  err5:
4414  	dwc3_gadget_free_endpoints(dwc);
4415  err4:
4416  	usb_put_gadget(dwc->gadget);
4417  	dwc->gadget = NULL;
4418  err3:
4419  	dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce,
4420  			dwc->bounce_addr);
4421  
4422  err2:
4423  	kfree(dwc->setup_buf);
4424  
4425  err1:
4426  	dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2,
4427  			dwc->ep0_trb, dwc->ep0_trb_addr);
4428  
4429  err0:
4430  	return ret;
4431  }

dwc3_gadget_init_endpoints会调用dwc3_gadget_init_endpoint依次初始化endpoint。在dwc3_gadget_init_endpoint中会分配dwc3_ep数据结构。然后根据endpint类型调用不同的初始化流程,主要就是初始化dep->endpoint.ops,并将这个ep挂到dwc->gadget->ep_list链表上。

3016  static int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum)
3017  {
3018  	struct dwc3_ep			*dep;
3019  	bool				direction = epnum & 1;
3020  	int				ret;
3021  	u8				num = epnum >> 1;
3022  
3023  	dep = kzalloc(sizeof(*dep), GFP_KERNEL);
3024  	if (!dep)
3025  		return -ENOMEM;
3026  
3027  	dep->dwc = dwc;
3028  	dep->number = epnum;
3029  	dep->direction = direction;
3030  	dep->regs = dwc->regs + DWC3_DEP_BASE(epnum);
3031  	dwc->eps[epnum] = dep;
3032  	dep->combo_num = 0;
3033  	dep->start_cmd_status = 0;
3034  
3035  	snprintf(dep->name, sizeof(dep->name), "ep%u%s", num,
3036  			direction ? "in" : "out");
3037  
3038  	dep->endpoint.name = dep->name;
3039  
3040  	if (!(dep->number > 1)) {
3041  		dep->endpoint.desc = &dwc3_gadget_ep0_desc;
3042  		dep->endpoint.comp_desc = NULL;
3043  	}
3044  
3045  	if (num == 0)
3046  		ret = dwc3_gadget_init_control_endpoint(dep);
3047  	else if (direction)
3048  		ret = dwc3_gadget_init_in_endpoint(dep);
3049  	else
3050  		ret = dwc3_gadget_init_out_endpoint(dep);
3051  
3052  	if (ret)
3053  		return ret;
3054  
3055  	dep->endpoint.caps.dir_in = direction;
3056  	dep->endpoint.caps.dir_out = !direction;
3057  
3058  	INIT_LIST_HEAD(&dep->pending_list);
3059  	INIT_LIST_HEAD(&dep->started_list);
3060  	INIT_LIST_HEAD(&dep->cancelled_list);
3061  
3062  	dwc3_debugfs_create_endpoint_dir(dep);
3063  
3064  	return 0;
3065  }

usb_ep_ops定义如下,为控制器端点的收发数据等函数。

2175  /* -------------------------------------------------------------------------- */
2176  
2177  static struct usb_endpoint_descriptor dwc3_gadget_ep0_desc = {
2178  	.bLength	= USB_DT_ENDPOINT_SIZE,
2179  	.bDescriptorType = USB_DT_ENDPOINT,
2180  	.bmAttributes	= USB_ENDPOINT_XFER_CONTROL,
2181  };
2182  
2183  static const struct usb_ep_ops dwc3_gadget_ep0_ops = {
2184  	.enable		= dwc3_gadget_ep0_enable,
2185  	.disable	= dwc3_gadget_ep0_disable,
2186  	.alloc_request	= dwc3_gadget_ep_alloc_request,
2187  	.free_request	= dwc3_gadget_ep_free_request,
2188  	.queue		= dwc3_gadget_ep0_queue,
2189  	.dequeue	= dwc3_gadget_ep_dequeue,
2190  	.set_halt	= dwc3_gadget_ep0_set_halt,
2191  	.set_wedge	= dwc3_gadget_ep_set_wedge,
2192  };
2193  
2194  static const struct usb_ep_ops dwc3_gadget_ep_ops = {
2195  	.enable		= dwc3_gadget_ep_enable,
2196  	.disable	= dwc3_gadget_ep_disable,
2197  	.alloc_request	= dwc3_gadget_ep_alloc_request,
2198  	.free_request	= dwc3_gadget_ep_free_request,
2199  	.queue		= dwc3_gadget_ep_queue,
2200  	.dequeue	= dwc3_gadget_ep_dequeue,
2201  	.set_halt	= dwc3_gadget_ep_set_halt,
2202  	.set_wedge	= dwc3_gadget_ep_set_wedge,
2203  };
2204  
2205  /* -------------------------------------------------------------------------- */

再继续看usb_gadget数据结构如下:

335  /**
336   * struct usb_gadget - represents a usb device
337   * @work: (internal use) Workqueue to be used for sysfs_notify()
338   * @udc: struct usb_udc pointer for this gadget
339   * @ops: Function pointers used to access hardware-specific operations.
340   * @ep0: Endpoint zero, used when reading or writing responses to
341   *	driver setup() requests
342   * @ep_list: List of other endpoints supported by the device.
343   * @speed: Speed of current connection to USB host.
344   * @max_speed: Maximal speed the UDC can handle.  UDC must support this
345   *      and all slower speeds.
346   * @ssp_rate: Current connected SuperSpeed Plus signaling rate and lane count.
347   * @max_ssp_rate: Maximum SuperSpeed Plus signaling rate and lane count the UDC
348   *	can handle. The UDC must support this and all slower speeds and lower
349   *	number of lanes.
350   * @state: the state we are now (attached, suspended, configured, etc)
351   * @name: Identifies the controller hardware type.  Used in diagnostics
352   *	and sometimes configuration.
353   * @dev: Driver model state for this abstract device.
354   * @isoch_delay: value from Set Isoch Delay request. Only valid on SS/SSP
355   * @out_epnum: last used out ep number
356   * @in_epnum: last used in ep number
357   * @mA: last set mA value
358   * @otg_caps: OTG capabilities of this gadget.
359   * @sg_supported: true if we can handle scatter-gather
360   * @is_otg: True if the USB device port uses a Mini-AB jack, so that the
361   *	gadget driver must provide a USB OTG descriptor.
362   * @is_a_peripheral: False unless is_otg, the "A" end of a USB cable
363   *	is in the Mini-AB jack, and HNP has been used to switch roles
364   *	so that the "A" device currently acts as A-Peripheral, not A-Host.
365   * @a_hnp_support: OTG device feature flag, indicating that the A-Host
366   *	supports HNP at this port.
367   * @a_alt_hnp_support: OTG device feature flag, indicating that the A-Host
368   *	only supports HNP on a different root port.
369   * @b_hnp_enable: OTG device feature flag, indicating that the A-Host
370   *	enabled HNP support.
371   * @hnp_polling_support: OTG device feature flag, indicating if the OTG device
372   *	in peripheral mode can support HNP polling.
373   * @host_request_flag: OTG device feature flag, indicating if A-Peripheral
374   *	or B-Peripheral wants to take host role.
375   * @quirk_ep_out_aligned_size: epout requires buffer size to be aligned to
376   *	MaxPacketSize.
377   * @quirk_altset_not_supp: UDC controller doesn't support alt settings.
378   * @quirk_stall_not_supp: UDC controller doesn't support stalling.
379   * @quirk_zlp_not_supp: UDC controller doesn't support ZLP.
380   * @quirk_avoids_skb_reserve: udc/platform wants to avoid skb_reserve() in
381   *	u_ether.c to improve performance.
382   * @is_selfpowered: if the gadget is self-powered.
383   * @deactivated: True if gadget is deactivated - in deactivated state it cannot
384   *	be connected.
385   * @connected: True if gadget is connected.
386   * @lpm_capable: If the gadget max_speed is FULL or HIGH, this flag
387   *	indicates that it supports LPM as per the LPM ECN & errata.
388   * @irq: the interrupt number for device controller.
389   *
390   * Gadgets have a mostly-portable "gadget driver" implementing device
391   * functions, handling all usb configurations and interfaces.  Gadget
392   * drivers talk to hardware-specific code indirectly, through ops vectors.
393   * That insulates the gadget driver from hardware details, and packages
394   * the hardware endpoints through generic i/o queues.  The "usb_gadget"
395   * and "usb_ep" interfaces provide that insulation from the hardware.
396   *
397   * Except for the driver data, all fields in this structure are
398   * read-only to the gadget driver.  That driver data is part of the
399   * "driver model" infrastructure in 2.6 (and later) kernels, and for
400   * earlier systems is grouped in a similar structure that's not known
401   * to the rest of the kernel.
402   *
403   * Values of the three OTG device feature flags are updated before the
404   * setup() call corresponding to USB_REQ_SET_CONFIGURATION, and before
405   * driver suspend() calls.  They are valid only when is_otg, and when the
406   * device is acting as a B-Peripheral (so is_a_peripheral is false).
407   */
408  struct usb_gadget {
409  	struct work_struct		work;
410  	struct usb_udc			*udc;
411  	/* readonly to gadget driver */
412  	const struct usb_gadget_ops	*ops;
413  	struct usb_ep			*ep0;
414  	struct list_head		ep_list;	/* of usb_ep */
415  	enum usb_device_speed		speed;
416  	enum usb_device_speed		max_speed;
417  
418  	/* USB SuperSpeed Plus only */
419  	enum usb_ssp_rate		ssp_rate;
420  	enum usb_ssp_rate		max_ssp_rate;
421  
422  	enum usb_device_state		state;
423  	const char			*name;
424  	struct device			dev;
425  	unsigned			isoch_delay;
426  	unsigned			out_epnum;
427  	unsigned			in_epnum;
428  	unsigned			mA;
429  	struct usb_otg_caps		*otg_caps;
430  
431  	unsigned			sg_supported:1;
432  	unsigned			is_otg:1;
433  	unsigned			is_a_peripheral:1;
434  	unsigned			b_hnp_enable:1;
435  	unsigned			a_hnp_support:1;
436  	unsigned			a_alt_hnp_support:1;
437  	unsigned			hnp_polling_support:1;
438  	unsigned			host_request_flag:1;
439  	unsigned			quirk_ep_out_aligned_size:1;
440  	unsigned			quirk_altset_not_supp:1;
441  	unsigned			quirk_stall_not_supp:1;
442  	unsigned			quirk_zlp_not_supp:1;
443  	unsigned			quirk_avoids_skb_reserve:1;
444  	unsigned			is_selfpowered:1;
445  	unsigned			deactivated:1;
446  	unsigned			connected:1;
447  	unsigned			lpm_capable:1;
448  	int				irq;
449  };

在usb_add_gadget中会创建usb_udc数据结构,usb_udc对于的就是usb device设备,它被挂载到udc_list全局链表。可以看到在这个函数中会调用device_add将usb_gadget和usb_udc的dev成员添加到系统中,执行完这个添加工作后,只是会在sys系统中显示设备的相关信息, 并不会匹配驱动。

1283  /**
1284   * usb_add_gadget - adds a new gadget to the udc class driver list
1285   * @gadget: the gadget to be added to the list.
1286   *
1287   * Returns zero on success, negative errno otherwise.
1288   * Does not do a final usb_put_gadget() if an error occurs.
1289   */
1290  int usb_add_gadget(struct usb_gadget *gadget)
1291  {
1292  	struct usb_udc		*udc;
1293  	int			ret = -ENOMEM;
1294  
1295  	udc = kzalloc(sizeof(*udc), GFP_KERNEL);
1296  	if (!udc)
1297  		goto error;
1298  
1299  	device_initialize(&udc->dev);
1300  	udc->dev.release = usb_udc_release;
1301  	udc->dev.class = udc_class;
1302  	udc->dev.groups = usb_udc_attr_groups;
1303  	udc->dev.parent = gadget->dev.parent;
1304  	ret = dev_set_name(&udc->dev, "%s",
1305  			kobject_name(&gadget->dev.parent->kobj));
1306  	if (ret)
1307  		goto err_put_udc;
1308  
1309  	ret = device_add(&gadget->dev);
1310  	if (ret)
1311  		goto err_put_udc;
1312  
1313  	udc->gadget = gadget;
1314  	gadget->udc = udc;
1315  
1316  	udc->started = false;
1317  
1318  	mutex_lock(&udc_lock);
1319  	list_add_tail(&udc->list, &udc_list);
1320  
1321  	ret = device_add(&udc->dev);
1322  	if (ret)
1323  		goto err_unlist_udc;
1324  
1325  	usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
1326  	udc->vbus = true;
1327  
1328  	/* pick up one of pending gadget drivers */
1329  	ret = check_pending_gadget_drivers(udc);
1330  	if (ret)
1331  		goto err_del_udc;
1332  
1333  	mutex_unlock(&udc_lock);
1334  
1335  	return 0;
1336  
1337   err_del_udc:
1338  	flush_work(&gadget->work);
1339  	device_del(&udc->dev);
1340  
1341   err_unlist_udc:
1342  	list_del(&udc->list);
1343  	mutex_unlock(&udc_lock);
1344  
1345  	device_del(&gadget->dev);
1346  
1347   err_put_udc:
1348  	put_device(&udc->dev);
1349  
1350   error:
1351  	return ret;
1352  }

usb_udc结构如下:

24  /**
25   * struct usb_udc - describes one usb device controller
26   * @driver: the gadget driver pointer. For use by the class code
27   * @dev: the child device to the actual controller
28   * @gadget: the gadget. For use by the class code
29   * @list: for use by the udc class driver
30   * @vbus: for udcs who care about vbus status, this value is real vbus status;
31   * for udcs who do not care about vbus status, this value is always true
32   * @started: the UDC's started state. True if the UDC had started.
33   *
34   * This represents the internal data structure which is used by the UDC-class
35   * to hold information about udc driver and gadget together.
36   */
37  struct usb_udc {
38  	struct usb_gadget_driver	*driver;
39  	struct usb_gadget		*gadget;
40  	struct device			dev;
41  	struct list_head		list;
42  	bool				vbus;
43  	bool				started;
44  };

usb device设备对应的驱动是usb_gadget_driver ,这个驱动是在usb_gadget_probe_driver里面根据控制器名字绑定的,usb_gadget_probe_driver何时调用我们会在随后的文章中介绍。

1524  int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
1525  {
1526  	struct usb_udc		*udc = NULL;
1527  	int			ret = -ENODEV;
1528  
1529  	if (!driver || !driver->bind || !driver->setup)
1530  		return -EINVAL;
1531  
1532  	mutex_lock(&udc_lock);
1533  	if (driver->udc_name) {
1534  		list_for_each_entry(udc, &udc_list, list) {
1535  			ret = strcmp(driver->udc_name, dev_name(&udc->dev));
1536  			if (!ret)
1537  				break;
1538  		}
1539  		if (ret)
1540  			ret = -ENODEV;
1541  		else if (udc->driver)
1542  			ret = -EBUSY;
1543  		else
1544  			goto found;
1545  	} else {
1546  		list_for_each_entry(udc, &udc_list, list) {
1547  			/* For now we take the first one */
1548  			if (!udc->driver)
1549  				goto found;
1550  		}
1551  	}
1552  
1553  	if (!driver->match_existing_only) {
1554  		list_add_tail(&driver->pending, &gadget_driver_pending_list);
1555  		pr_info("udc-core: couldn't find an available UDC - added [%s] to list of pending drivers\n",
1556  			driver->function);
1557  		ret = 0;
1558  	}
1559  
1560  	mutex_unlock(&udc_lock);
1561  	if (ret)
1562  		pr_warn("udc-core: couldn't find an available UDC or it's busy\n");
1563  	return ret;
1564  found:
1565  	ret = udc_bind_to_driver(udc, driver);
1566  	mutex_unlock(&udc_lock);
1567  	return ret;
1568  }

usb devcie控制器驱动大概就是这些内容,我们后面介绍如何利用这个控制器驱动实现各种各样的usb设备。

标签:dwc3,usb,udc,gadget,ret,dwc,Linux
From: https://blog.csdn.net/liverdream/article/details/145263130

相关文章

  • LibXL 4.5.1 for win/linux/Mac/iOS Patch
    DirectreadingandwritingExcelfilesLibXLisalibrarythatcanreadandwriteExcelfiles.Itdoesn'trequireMicrosoftExceland.NETframework,combinesaneasytouseandpowerfulfeatures.LibrarycanbeusedtoGenerateanewspreadsheetfro......
  • Linux升级rsync
    介绍:查看当前版本: rsync --version找到安装目录:whichrsync在管网处下载最新tar.gz包,解压后,进入目录,依次执行以下命令:第一步:######配置 sudo ./configure--prefix=/usr/local######升级新版本可能会报错:Configurefoundthefollowingissues:-Failedtofindxx......
  • linux文件IO:select
    select电平触发#include<sys/time.h>#include<sys/types.h>#include<unistd.h>intselect(intn,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,structtimeval*timeout);在指定的文件描述符准备好I/O之前或超过一定时间限制,select调用会被阻塞readfds文件描......
  • How to set up File Transfer Protocol(FTP) server in Linux
    Step1:InstallvsftpdTosetupanFTPserverinLinux,first,youhavetoensurevsftpdisinstalled:ForUbuntu/Debian:sudoaptupdatesudoaptinstallvsftpd-yForCentOS/RHEL:sudoyuminstallvsftpd-yStep2:BasicConfigurationofvsftpdConfigu......
  • 如何在 Linux 服务器上设置 FTP 文件传输协议
    第一步:安装vsftpd要在Linux上设置FTP服务器,首先需要确保已安装vsftpd。对于Ubuntu/Debian系统:sudoaptupdatesudoaptinstallvsftpd-y对于CentOS/RHEL系统:sudoyuminstallvsftpd-y第二步:配置vsftpd配置vsftpd以允许基本的FTP连接并设置用户限......
  • Windows和Linux系统安装东方通
    1.Windows系统安装东方通1.1安装jdk1.2下载安装文件及license文件官网:https://www.tongtech.com/sy.html下载windows系统文件1.3在D盘下面创建TongWeb文件夹,上传文件1.4解压文件,把license文件放到bin同级目录下1.5启动,进入bin目录下启动双击:startserver.bat停止......
  • Arch Linux - 中文乱码问题
    解决中文乱码问题,可以参考这这篇文章:Localization/SimplifiedChinese主要分成3个步骤locale配置中文字体不同软件的字体设置locale配置locale配置,其实是配置locale的环境变量LANGUAGELC_ALLLC_xxx,xxx表示不同的分类:CTYPE,TIME,...LANG可以执行命令locale查......
  • 一站式云原生支持,Alibaba Cloud Linux性能有多强?
    随着云计算技术的高速发展,企业对操作系统的需求不再局限于传统的服务器环境,而是更加关注与云原生架构的兼容性、性能优化以及系统的可扩展性。在这样的背景下,AlibabaCloudLinux应运而生,作为一款由阿里云自主研发的Linux操作系统,它专为云计算环境进行了深度优化,为企业和开发者......
  • Linux 笔记
    目录Linux目录结构Linux目录与Windows目录对比Windows目录结构Linux目录结构Linux世界里---一切皆文件Linux目录结构详解/bin/sbin/home/root/boot/lib/etc/usr/proc,别动/srv,别动/sys,别动/tmp/dev/media/mnt/opt/usr/local/var/selinux常用快捷键案例常用命令开机/......
  • 【linux】文件与目录命令 - vim
    文章目录1.基本用法2.常用参数3.用法举例4.多种模式5.注意事项vim是一款功能强大的文本编辑器,适用于代码编辑和日常文本处理。它是vi的增强版,支持多种模式(如普通模式、插入模式和命令模式)以及插件扩展。1.基本用法语法:vim[选项][文件]功能:编......