- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我开发了这个简单的内核模块,它通过使用 FIFO 队列和定时器来模拟串口(从硬件读取:从队列中取出,写入硬件:插入到队列中)。
源代码如下所示。
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/module.h>
#define TINY_SERIAL_DEBUG
#define pr_fmt(fmt) "tiny_serial: " fmt
#if defined(TINY_SERIAL_DEBUG)
#define DBG(fmt, ...) printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
#else
#define DBG(fmt, ...) no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#endif
#define DRIVER_AUTHOR "Me Me <me@me.com>"
#define DRIVER_DESC "Tiny serial driver"
/* Module information */
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");
#define DELAY_TIME 100// HZ * 2 /* 2 seconds per character */
#define TINY_DATA_CHARACTER 't'
#define TINY_SERIAL_MAJOR 240 //240 /* experimental range */
#define TINY_SERIAL_MINORS 1 //1 /* only have one minor */
#define UART_NR 1 /* only use one port */
#define TINY_SERIAL_NAME "ttytiny"
#define MY_NAME TINY_SERIAL_NAME
#define BUF_SIZE 4096
static char buf[BUF_SIZE];
static char *read_ptr;
static char *write_ptr;
static struct timer_list *timer;
static void serial_out(char data)
{
*write_ptr = data;
write_ptr++;
if (write_ptr >= buf + BUF_SIZE)
write_ptr = buf;
}
static void serial_in(char *data)
{
if (read_ptr == NULL) {
DBG("pointer is null !\n");
}
if (read_ptr && (read_ptr != write_ptr)) {
*data = *read_ptr;
read_ptr++;
if(read_ptr >= buf + BUF_SIZE)
read_ptr = buf;
}
}
static void tiny_stop_tx(struct uart_port *port)
{
DBG("tiny_stop_tx()\n");
}
static void tiny_stop_rx(struct uart_port *port)
{
DBG("tiny_stop_rx()\n");
}
static void tiny_enable_ms(struct uart_port *port)
{
DBG("tiny_enable_ms()\n");
}
static void tiny_rx_chars(struct uart_port *port, int size)
{
int i = 0;
char byte;
char flag;
struct tty_port *tty = &port->state->port;
if (size <= 0) {
return;
}
while (size--) {
serial_in(&byte);
DBG("read: 0x%2x\n", byte);
flag = TTY_NORMAL;
port->icount.rx++;
if (uart_handle_sysrq_char(port, byte)) {
DBG("found ignore char !\n");
goto ignore_char;
}
uart_insert_char(port, 0, 0, byte, flag);
ignore_char:
i ++;
}
tty_flip_buffer_push(tty);
DBG("push to user space !\n");
}
static int tiny_tx_chars(struct uart_port *port)
{
struct circ_buf *xmit = &port->state->xmit;
int count;
DBG("tiny_tx_chars()\n");
if (port->x_char) {
DBG("wrote 0x%2x\r\n", port->x_char);
port->icount.tx++;
port->x_char = 0;
return 0;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
tiny_stop_tx(port);
return 0;
}
count = port->fifosize >> 1;
do {
DBG("wrote 0x%2x\r\n", xmit->buf[xmit->tail]);
serial_out(xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
if (uart_circ_empty(xmit))
break;
} while (--count > 0);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
tiny_stop_tx(port);
return ((port->fifosize >> 1) - count + 1);
}
static void tiny_start_tx(struct uart_port *port)
{
DBG("tiny_start_tx()\n");
}
static void tiny_timer(unsigned long data)
{
struct uart_port *port;
struct tty_port *tport;
int ret = 0;
DBG("tiny_timer()\n");
port = (struct uart_port *)data;
if (!port)
return;
if (!port->state)
return;
tport = &port->state->port;
/* resubmit the timer again */
timer->expires = jiffies + DELAY_TIME;
add_timer(timer);
/* see if we have any data to transmit */
ret = tiny_tx_chars(port);
tiny_rx_chars(port, ret);
}
static unsigned int tiny_tx_empty(struct uart_port *port)
{
DBG("tiny_tx_empty()\n");
return 0;
}
static unsigned int tiny_get_mctrl(struct uart_port *port)
{
DBG("tiny_get_mctrl()\n");
return 0;
}
static void tiny_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
DBG("tiny_set_mctrl()\n");
}
static void tiny_break_ctl(struct uart_port *port, int break_state)
{
DBG("tiny_set_mctrl()\n");
}
static void tiny_set_termios(struct uart_port *port,
struct ktermios *new, struct ktermios *old)
{
int baud, quot, cflag = new->c_cflag;
DBG("tiny_set_termios()\n");
/* get the byte size */
switch (cflag & CSIZE) {
case CS5:
DBG(" - data bits = 5\n");
break;
case CS6:
DBG(" - data bits = 6\n");
break;
case CS7:
DBG(" - data bits = 7\n");
break;
default: // CS8
DBG(" - data bits = 8\n");
break;
}
/* determine the parity */
if (cflag & PARENB)
if (cflag & PARODD)
DBG(" - parity = odd\n");
else
DBG(" - parity = even\n");
else
DBG(" - parity = none\n");
/* figure out the stop bits requested */
if (cflag & CSTOPB)
DBG(" - stop bits = 2\n");
else
DBG(" - stop bits = 1\n");
/* figure out the flow control settings */
if (cflag & CRTSCTS)
DBG(" - RTS/CTS is enabled\n");
else
DBG(" - RTS/CTS is disabled\n");
/* Set baud rate */
baud = uart_get_baud_rate(port, new, old, 9600, 115200);
quot = uart_get_divisor(port, baud);
}
static int tiny_startup(struct uart_port *port)
{
/* this is the first time this port is opened */
/* do any hardware initialization needed here */
DBG("tiny_startup()\n");
/* create our timer and submit it */
if (!timer) {
timer = kmalloc(sizeof(*timer), GFP_KERNEL);
if (!timer)
return -ENOMEM;
init_timer(timer);
}
timer->data = (unsigned long)port;
timer->expires = jiffies + DELAY_TIME;
timer->function = tiny_timer;
add_timer(timer);
return 0;
}
static void tiny_shutdown(struct uart_port *port)
{
/* The port is being closed by the last user. */
/* Do any hardware specific stuff here */
DBG("tiny_shutdown()\n");
/* shut down our timer */
del_timer(timer);
}
static const char *tiny_type(struct uart_port *port)
{
DBG("tiny_type()\n");
return "tinytty";
}
static void tiny_release_port(struct uart_port *port)
{
DBG("tiny_release_port()\n");
}
static int tiny_request_port(struct uart_port *port)
{
DBG("tiny_request_port()\n");
return 0;
}
static void tiny_config_port(struct uart_port *port, int flags)
{
DBG("tiny_config_port()\n");
}
static int tiny_verify_port(struct uart_port *port, struct serial_struct *ser)
{
DBG("tiny_verify_port()\n");
return 0;
}
static struct uart_ops tiny_ops = {
.tx_empty = tiny_tx_empty,
.set_mctrl = tiny_set_mctrl,
.get_mctrl = tiny_get_mctrl,
.stop_tx = tiny_stop_tx,
.start_tx = tiny_start_tx,
.stop_rx = tiny_stop_rx,
.enable_ms = tiny_enable_ms,
.break_ctl = tiny_break_ctl,
.startup = tiny_startup,
.shutdown = tiny_shutdown,
.set_termios = tiny_set_termios,
.type = tiny_type,
.release_port = tiny_release_port,
.request_port = tiny_request_port,
.config_port = tiny_config_port,
.verify_port = tiny_verify_port,
};
static struct uart_port tiny_port = {
.ops = &tiny_ops,
.line = 0,
.type = 104,
.iotype = SERIAL_IO_PORT,
.fifosize = 128,
.flags = ASYNC_BOOT_AUTOCONF,
.irq = 0,
};
static struct uart_driver tiny_reg = {
.owner = THIS_MODULE,
.driver_name = TINY_SERIAL_NAME,
.dev_name = TINY_SERIAL_NAME,
.major = TINY_SERIAL_MAJOR,
.minor = TINY_SERIAL_MINORS,
.nr = UART_NR,
};
static int __init tiny_init(void)
{
int result;
DBG(KERN_INFO "Tiny serial driver loaded\n");
result = uart_register_driver(&tiny_reg);
if (result) {
DBG("tiny_init() error!\n");
return result;
}
result = uart_add_one_port(&tiny_reg, &tiny_port);
if (result) {
DBG("uart_add_one_port() error!\n");
uart_unregister_driver(&tiny_reg);
}
read_ptr = buf;
write_ptr = buf;
return result;
}
module_init(tiny_init);
然后,我编写了一个简单的测试应用程序来配置端口设置(波特率、奇偶校验、停止位等)并启动写入 + 读取事务,读取之前写入的字符串。
源代码如下所示。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#define PAR_NONE 0
#define PAR_EVEN 1
#define PAR_ODD 2
#define DATA_8BIT 1
#define DATA_7BIT 2
#define STOP_1BIT 1
#define STOP_2BIT 2
struct tiny_op {
int max_fd;
int fd;
fd_set rfds;
fd_set wfds;
fd_set efds;
struct timeval r_timeout;
struct timeval w_timeout;
};
static struct tiny_op tops;
static void set_termios(struct termios *termios, int baudrate, int parity, int bits, int stop)
{
termios->c_cflag |= CLOCAL | CREAD;
termios->c_cflag &= ~CSIZE;
switch (bits) {
case DATA_7BIT:
termios->c_cflag |= CS7;
break;
case DATA_8BIT:
termios->c_cflag |= CS8;
break;
default:
termios->c_cflag |= CS8;
break;
}
switch (parity) {
case PAR_NONE:
termios->c_cflag &= ~PARENB;
termios->c_cflag &= ~PARODD;
break;
case PAR_EVEN:
termios->c_cflag |= PARENB;
termios->c_cflag &= ~PARODD;
break;
case PAR_ODD:
termios->c_cflag |= PARENB;
termios->c_cflag |= PARODD;
break;
default:
termios->c_cflag &= ~PARENB;
termios->c_cflag &= ~PARODD;
break;
}
switch (stop) {
case STOP_1BIT:
termios->c_cflag &= ~CSTOPB;
break;
case STOP_2BIT:
termios->c_cflag |= CSTOPB;
break;
default:
termios->c_cflag &= ~CSTOPB;
break;
}
termios->c_iflag |= INPCK | ISTRIP;
termios->c_lflag = 0;
termios->c_oflag = 0;
termios->c_cc[VTIME] = 5;
termios->c_cc[VMIN] = 0;
cfsetspeed(termios, baudrate);
}
static int tiny_write(struct tiny_op *op, char *buff, int size)
{
int ret = -1;
int len = 0;
op->w_timeout.tv_sec = 5;
op->w_timeout.tv_usec = 0;
ret = select(op->max_fd, NULL, &op->wfds, &op->efds, &op->w_timeout);
if (ret < 0) {
printf("[TINY SERIAL] Select fallita (write) !\n");
return -1;
} if (0 == ret) {
printf("[TINY SERIAL] Select time-out (write) !\n");
} else {
if (FD_ISSET(op->fd, &op->efds)) {
printf("[TINY SERIAL] Attenzione: errore in scrittura!\n");
return -1;
}
if (FD_ISSET(op->fd, &op->wfds)) {
printf("[TINY SERIAL] Scrittura pronta, procedo !\n");
len = write(op->fd, (const void *)buff, size);
if (len == size) {
printf("[TINY SERIAL] Scrittura completata!\n");
} else {
printf("[TINY SERIAL] Scrittura parzialmente completata, scritti : = %d\n", len);
}
}
}
return 0;
}
static int tiny_read(struct tiny_op *op, char *buff, int size)
{
int ret = -1;
int len = 0;
op->r_timeout.tv_sec = 5;
op->r_timeout.tv_usec = 0;
ret = select(op->max_fd, &op->rfds, NULL, &op->efds, &op->r_timeout);
if (ret < 0) {
printf("[TINY SERIAL] Select fallita (read) !\n");
return -1;
} if (0 == ret) {
printf("[TINY SERIAL] Select time-out (read)!\n");
} else {
if (FD_ISSET(op->fd, &op->efds)) {
printf("[TINY SERIAL] Attenzione: errore in lettura!\n");
return -1;
}
if (FD_ISSET(op->fd, &op->rfds)) {
printf("[TINY SERIAL] Dati da leggere disponibili!\n");
len = read(op->fd, (void *)buff, size);
printf("[TINY SERIAL] Lettura da seriale: %s, len: %d\n", buff, len);
}
}
return 0;
}
int main(int argc, char **argv)
{
int fd = -1, ret = -1;
struct termios oldtio, newtio;
char *str = {"Hello world!!\0"};
char buff[strlen(str)];
if(argc == 1){
printf("[TINY DRIVER] Inserisci il device seriale da testare.\n");
return -1;
}
char * device = argv[1];
struct stat file_infos;
if(strlen(device) == 0){
printf("[TINY DRIVER] Seleziona un device corretto.\n");
return -1;
}
printf("[TINY DRIVER] Hai selezionato il device: %s\n", device);
if(stat(device, &file_infos) < 0){
printf("[TINY DRIVER] Attenzione: errore nell'accesso al device selezionato: %s, riprova con un altro dispositivo.\n", device);
return -1;
}
bzero((void *)&oldtio, sizeof(oldtio));
bzero((void *)&newtio, sizeof(newtio));
fd = open(device, O_RDWR | O_NONBLOCK | O_SYNC);
if (fd == -1) {
printf("[TINY SERIAL] failed to open /dev/ttytiny0 !\n");
return -1;
}
printf("[TINY SERIAL] succeed to open /dev/ttytiny0 !\n");
ret = tcgetattr(fd, &oldtio);
if (ret != 0) {
printf("[TINY SERIAL] failed to get attr !\n");
close(fd);
return -1;
}
set_termios(&newtio, B38400, PAR_EVEN, DATA_8BIT, STOP_2BIT);
tcflush(fd, TCIOFLUSH);
ret = tcsetattr(fd, TCSANOW, &newtio);
if (ret != 0) {
printf("[TINY SERIAL] failed to set termios !\n");
close(fd);
return -1;
}
tops.fd = fd;
tops.max_fd = tops.fd + 1;
FD_ZERO(&tops.rfds);
FD_ZERO(&tops.wfds);
FD_ZERO(&tops.efds);
FD_SET(tops.fd, &tops.rfds);
FD_SET(tops.fd, &tops.wfds);
FD_SET(tops.fd, &tops.efds);
if (tiny_write(&tops, str, strlen(str)) != 0) {
close(fd);
return -1;
}
if (tiny_read(&tops, buff, sizeof(buff)) != 0) {
close(fd);
return -1;
}
ret = tcsetattr(fd, TCSANOW, &oldtio);
if (ret != 0) {
printf("[TINY SERIAL] Errore nel reset delle impostazioni.\n");
}else{
printf("[TINY SERIAL] Impostazioni resettate correttamente.\n");
}
ret = tcflush(fd, TCIOFLUSH);
if(ret != 0){
printf("[TINY SERIAL] Errore nel flushing dei dati (finale) !\n");
}else{
printf("[TINY SERIAL] Dati flushati correttamente!\n");
}
//Program hangs on this call
ret = close(fd);
if (ret != 0) {
printf("[TINY SERIAL] Errore nella Chiusura del file !\n");
return -1;
}else{
printf("[TINY SERIAL] Chiusura del file avvenuta correttamente !\n");
}
return 0;
}
我的问题是:测试应用程序工作正常(我可以写入和读取我自己的字符串)直到它到达 close(2)功能:它永远卡在那里,没有到达程序的末尾(我必须用 CTRL+C 关闭它,然后当内核模块调用 tiny_shutdown() 函数时它正确关闭)。
我也尝试编写一个简单的程序来打开和关闭/dev/ttytiny0 设备,但结果是一样的(虽然我注意到,如果我删除 close(2) 操作,程序仍然挂起而没有终止,但这次我无法使用 CTRL+C 将其关闭。
任何有关该主题的书籍或 Material 的链接/引用将不胜感激。
提前致谢!
编辑:在此处报告内核日志消息(在运行测试应用程序时)
[ 446.862221] tiny_ser: module verification failed: signature and/or required key missing - tainting kernel
[ 446.864143] tiny_serial: 6Tiny serial driver loaded
[ 486.715801] tiny_serial: tiny_startup()
[ 486.715812] tiny_serial: tiny_set_termios()
[ 486.715814] tiny_serial: - data bits = 8
[ 486.715816] tiny_serial: - parity = none
[ 486.715818] tiny_serial: - stop bits = 1
[ 486.715820] tiny_serial: - RTS/CTS is disabled
[ 486.715824] tiny_serial: tiny_set_mctrl()
[ 486.715853] tiny_serial: tiny_set_termios()
[ 486.715856] tiny_serial: - data bits = 8
[ 486.715857] tiny_serial: - parity = even
[ 486.715859] tiny_serial: - stop bits = 2
[ 486.715861] tiny_serial: - RTS/CTS is disabled
[ 486.715943] tiny_serial: tiny_start_tx()
[ 487.116105] tiny_serial: tiny_timer()
[ 487.116171] tiny_serial: tiny_tx_chars()
[ 487.116183] tiny_serial: wrote 0x42
[ 487.116189] tiny_serial: wrote 0x75
[ 487.116196] tiny_serial: wrote 0x6f
[ 487.116202] tiny_serial: wrote 0x6e
[ 487.116208] tiny_serial: wrote 0x61
[ 487.116214] tiny_serial: wrote 0x73
[ 487.116220] tiny_serial: wrote 0x65
[ 487.116226] tiny_serial: wrote 0x72
[ 487.116232] tiny_serial: wrote 0x61
[ 487.116238] tiny_serial: wrote 0x20
[ 487.116245] tiny_serial: wrote 0x64
[ 487.116251] tiny_serial: wrote 0x72
[ 487.116257] tiny_serial: wrote 0x69
[ 487.116263] tiny_serial: wrote 0x76
[ 487.116269] tiny_serial: wrote 0x65
[ 487.116275] tiny_serial: wrote 0x72
[ 487.116281] tiny_serial: wrote 0x21
[ 487.116287] tiny_serial: wrote 0x21
[ 487.116295] tiny_serial: tiny_stop_tx()
[ 487.116303] tiny_serial: read: 0x42
[ 487.116312] tiny_serial: read: 0x75
[ 487.116318] tiny_serial: read: 0x6f
[ 487.116324] tiny_serial: read: 0x6e
[ 487.116330] tiny_serial: read: 0x61
[ 487.116337] tiny_serial: read: 0x73
[ 487.116343] tiny_serial: read: 0x65
[ 487.116349] tiny_serial: read: 0x72
[ 487.116355] tiny_serial: read: 0x61
[ 487.116361] tiny_serial: read: 0x20
[ 487.116367] tiny_serial: read: 0x64
[ 487.116373] tiny_serial: read: 0x72
[ 487.116379] tiny_serial: read: 0x69
[ 487.116385] tiny_serial: read: 0x76
[ 487.116391] tiny_serial: read: 0x65
[ 487.116397] tiny_serial: read: 0x72
[ 487.116403] tiny_serial: read: 0x21
[ 487.116409] tiny_serial: read: 0x21
[ 487.116444] tiny_serial: push to user space !
[ 487.116565] tiny_serial: tiny_start_tx()
[ 487.116709] tiny_serial: tiny_set_termios()
[ 487.116713] tiny_serial: - data bits = 8
[ 487.116715] tiny_serial: - parity = none
[ 487.116717] tiny_serial: - stop bits = 1
[ 487.116719] tiny_serial: - RTS/CTS is disabled
[ 487.116746] tiny_serial: tiny_tx_empty()
[ 487.516021] tiny_serial: tiny_timer()
[ 487.516094] tiny_serial: tiny_tx_chars()
[ 487.516104] tiny_serial: tiny_stop_tx()
[ 487.915917] tiny_serial: tiny_timer()
[ 487.915960] tiny_serial: tiny_tx_chars()
[ 487.915971] tiny_serial: tiny_stop_tx()
[ 505.910955] tiny_serial: tiny_timer()
[ 505.910968] tiny_serial: tiny_tx_chars()
[ 505.910971] tiny_serial: tiny_stop_tx()
[ 506.455320] tiny_serial: tiny_timer()
[ 506.455332] tiny_serial: tiny_tx_chars()
[ 506.455335] tiny_serial: tiny_stop_tx()
[ 506.855344] tiny_serial: tiny_timer()
[ 506.855428] tiny_serial: tiny_tx_chars()
[ 506.855437] tiny_serial: tiny_stop_tx()
[ 507.255499] tiny_serial: tiny_timer()
[ 507.255563] tiny_serial: tiny_tx_chars()
[ 507.255572] tiny_serial: tiny_stop_tx()
[ 507.655342] tiny_serial: tiny_timer()
[ 507.655401] tiny_serial: tiny_tx_chars()
[ 507.655411] tiny_serial: tiny_stop_tx()
[ 507.755090] tiny_serial: tiny_stop_rx()
[ 507.755100] tiny_serial: tiny_tx_empty()
[ 507.755103] tiny_serial: tiny_set_mctrl()
[ 507.755105] tiny_serial: tiny_shutdown()
[ 507.755108] tiny_serial: tiny_shutdown() - after del_timer()
请注意,当我使用 CTRL+C 终止测试应用程序执行时,将调用序列 tiny_stop_rx() - tiny_tx_empty() - tiny_set_mctrl() - tiny_shutdown()。
其他重复消息(序列 tiny_timer() - tiny_tx_chars() - tiny_stop_tx())由定时器生成,定时器检查是否必须传输某些内容(但队列为空,因此它再次休眠)。
当然,测试应用程序日志显示正确的行为,直到到达 close() 函数。
最佳答案
您的实现从 tx_empty()
返回 0
,这意味着“不为空”。
来自 kernel.org/doc/Documentation/serial/driver :
tx_empty(port)
This function tests whether the transmitter fifo and shifter for the port described by 'port' is empty. If it is empty, this function should return
TIOCSER_TEMT
, otherwise return 0. If the port does not support this operation, then it should returnTIOCSER_TEMT
.
关于c - 串口卡在 close() 上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51123691/
在 Android 的 API > 19 中是否有任何方法可以获取可移动 SD 卡的路径? 与外部 SD 卡一样,我们有 Environment.getExternalStorageDirectory
一些 Android 设备有 microSD(或其他存储卡)插槽,通常安装为 /storage/sdcard1 据我所知,自 Android 4.4 起 Google 限制了对此内存的访问,并在 An
我使用 Java Card 2.1.2 SDK 和 GPShell 作为与设备通信的方式在 Java Card 上构建一个项目。我从 GpShell 测试了 helloworld 示例,并成功发送了
我开发了一个应用程序,它有一个来电接收器,它适用于所有手机。一位用户有一部双 SIM 卡安卓手机。该应用程序适用于第一张 SIM 卡。但是当有人调用他的第二张 SIM 卡时,我们的应用程序不会被调用。
我有一个带预览的文件输入。 这是笔 Codepen 我想强制高度,我无法理解我该怎么做。我想将此组件的高度固定为 300px(示例),我还需要保持加载图像的正确纵横比,用灰色背景填充空白。现在我保持宽
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 6年前关闭。 Improve this qu
我正在使用此代码访问 SD card : import os from os.path import join from jnius import autoclass #from android.pe
我正在为数据记录设备编写固件。它以 20 Hz 的频率从传感器读取数据并将数据写入 SD 卡。但是,向SD卡写入数据的时间并不一致(大约200-300 ms)。因此,一种解决方案是以一致的速率将数据写
我正在使用以下代码将视频放到网站上,但是在垂直方向上,手机屏幕上只能看到视频的左半部分 我不是网络开发人员。有人可以告诉我确切的内容吗,如何使其正确放置在手机屏幕上? 是在youtube iframe
我正在使用 Vuetify 1.5 和 Vuetify 网格系统来设置我的布局。现在我有一个组件 HelloWorld我将其导入到我的 Parent 中成分。我已经在我的 HelloWorld 中设置
我使用 python 制作了一个简单的二十一点游戏。我制作了游戏的其余部分,但我正在努力放入 ASCII 卡,所以这只是代码的一小部分。我尝试将 * len(phand) 放在附加行的末尾。虽然这确实
我正在使用玩家卡设置 Twitter 卡。它可以在预览工具中运行,但文档说它需要在“twitter.com 现代桌面浏览器? native iOs 和 Android Twitter 应用程序?mob
任何旧的 GSM 兼容 SIM 卡(3G USIM 的奖励)。 我想我需要一些硬件?谁能为业余爱好者推荐一些便宜的东西,以及一些更专业的东西? 我认为会有一个带有硬件的 API 的完整文档,所以也许这
我使用 python 制作了一个简单的二十一点游戏。我制作了游戏的其余部分,但我正在努力放入 ASCII 卡,所以这只是代码的一小部分。我尝试将 * len(phand) 放在附加行的末尾。虽然这确实
我记得前一段时间读到有 cpu 卡供系统添加额外的处理能力来进行大规模并行化。任何人都有这方面的经验和任何资源来研究项目的硬件和软件方面吗?这项技术是否不如传统集群?它更注重功率吗? 最佳答案 有两个
我检查外部存储是否已安装并且可用于读/写,然后从中读取。我使用的是确切的官方 Android 示例代码 ( from here )。 它说外部存储未安装。 getExternalFilesDir(nu
在 Android 2.1 及更低版本中,Android 应用程序可以请求下载到 SD 卡上吗?另外我想知道应用程序是否可以请求一些包含视频的文件夹下载到 SD 卡上?以及如何做到这一点? 提前致谢。
我们编写了一个 Windows 设备驱动程序来访问我们的自定义 PCI 卡。驱动程序使用 CreateFile 获取卡的句柄。 我们最近在一次安装中遇到了问题,卡似乎停止工作了。我们尝试更换卡(更换似
有些新设备(例如 Samsung Galaxy)带有两个 SD 卡。我想知道是否有任何方法可以确定设备是否有两张 SD 卡或一张 SD 卡。谢谢 最佳答案 我认为唯一的方法是使用 检查可用根的列表 F
我正在尝试将文件读/写到 SD 卡。我已经尝试在我的真实手机和 Eclipse 中的模拟器上执行此操作。在这两种设备上,对/mnt/sdcard/或/sdcard 的权限仅为“d--------”,我
我是一名优秀的程序员,十分优秀!